30 #ifndef OOMPH_TRIANGLE_MESH_TEMPLATE_CC
31 #define OOMPH_TRIANGLE_MESH_TEMPLATE_CC
36 #include "../generic/map_matrix.h"
37 #include "../generic/multi_domain.h"
38 #include "../generic/projection.h"
39 #include "../generic/face_element_as_geometric_object.h"
48 template<
class ELEMENT>
50 const bool &use_attributes)
53 MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(2);
56 unsigned nelem = Tmp_mesh_pt->nelement();
57 Element_pt.resize(nelem);
60 unsigned nnode_scaffold = Tmp_mesh_pt->nnode();
64 std::map<Node*, unsigned> old_global_number;
67 for (
unsigned inod = 0; inod < nnode_scaffold; inod++)
69 Node* old_node_pt = Tmp_mesh_pt->node_pt(inod);
70 old_global_number[old_node_pt] = inod;
74 Oomph_vertex_nodes_id.
resize(nnode_scaffold);
77 Node_pt.resize(nnode_scaffold, 0);
80 unsigned nbound = Tmp_mesh_pt->nboundary();
83 set_nboundary(nbound);
84 Boundary_element_pt.resize(nbound);
85 Face_index_at_boundary.resize(nbound);
91 Boundary_region_element_pt.resize(nbound);
92 Face_index_region_at_boundary.resize(nbound);
96 for (
unsigned e = 0;
e < nelem;
e++)
98 Element_pt[
e] =
new ELEMENT;
102 unsigned nnod_el = Tmp_mesh_pt->finite_element_pt(0)->nnode();
107 std::map<Node*, unsigned> global_number;
108 unsigned global_count = 0;
111 std::map<double, Vector<FiniteElement*> > element_attribute_map;
118 element_attribute_map[0].resize(0);
122 for (
unsigned e = 0;
e < nelem;
e++)
125 for (
unsigned j = 0; j < nnod_el; j++)
128 Node* scaffold_node_pt = Tmp_mesh_pt->finite_element_pt(
e)->node_pt(j);
132 unsigned j_global = global_number[scaffold_node_pt];
138 Oomph_vertex_nodes_id[global_count] =
139 old_global_number[scaffold_node_pt];
143 std::set<unsigned>* boundaries_pt;
147 Node* new_node_pt = 0;
150 if (boundaries_pt != 0)
154 finite_element_pt(
e)->construct_boundary_node(j,time_stepper_pt);
157 for (std::set<unsigned>::iterator it = boundaries_pt->begin(); it
158 != boundaries_pt->end(); ++it)
160 add_boundary_node(*it, new_node_pt);
167 new_node_pt = finite_element_pt(
e)->construct_node(j,time_stepper_pt);
174 global_number[scaffold_node_pt] = global_count;
180 Node_pt[global_count - 1] = new_node_pt;
183 for (
unsigned i = 0;
i < finite_element_pt(
e)->dim();
i++)
185 new_node_pt->
x(
i) = scaffold_node_pt->
x(
i);
191 finite_element_pt(
e)->node_pt(j) = Node_pt[j_global - 1];
198 element_attribute_map[Tmp_mesh_pt->element_attribute(
e)].push_back(
199 finite_element_pt(
e));
207 unsigned n_attribute = element_attribute_map.size();
210 this->Region_attribute.resize(n_attribute);
215 element_attribute_map.begin(); it!=element_attribute_map.end(); ++it)
217 this->Region_attribute[count] = it->first;
218 Region_element_pt[
static_cast<unsigned>(Region_attribute[count])] =
229 unsigned boundary_id=0;
233 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
234 unsigned dim = finite_element_pt(0)->dim();
240 unsigned n_node = finite_element_pt(0)->nnode();
243 unsigned n_global_edge = Tmp_mesh_pt->nglobal_edge();
247 for (
unsigned e = 0;
e < nelem;
e++)
251 FiniteElement*
const tmp_elem_pt = Tmp_mesh_pt->finite_element_pt(
e);
254 unsigned n_edge_node = 3 * (n_node_1d - 1);
258 for (
unsigned n = n_edge_node;
n < n_node; ++
n)
268 for (
unsigned i = 0;
i < dim;
i++)
274 Node_pt.push_back(new_node_pt);
282 for (
unsigned j = 0; j < 3; j++)
285 boundary_id = Tmp_mesh_pt->edge_boundary(
e, j);
288 unsigned edge_index = Tmp_mesh_pt->edge_index(
e, j);
291 if (nodes_on_global_edge[edge_index].size() == 0)
294 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
297 Node* new_node_pt = 0;
304 this->add_boundary_node(boundary_id - 1, new_node_pt);
317 for (
unsigned i = 0;
i < dim;
i++)
323 Node_pt.push_back(new_node_pt);
326 nodes_on_global_edge[edge_index].push_back(new_node_pt);
338 for (
unsigned j2 = 0; j2 < n_node_1d - 2; ++j2)
342 elem_pt->
node_pt(
n) = nodes_on_global_edge[edge_index][n_node_1d - 3
352 Boundary_element_pt[boundary_id - 1].push_back(elem_pt);
355 Face_index_at_boundary[boundary_id - 1].push_back((j + 2) % 3);
360 unsigned tmp_region =
361 static_cast<unsigned> (Tmp_mesh_pt->element_attribute(
e));
363 Boundary_region_element_pt[boundary_id - 1]
364 [tmp_region].push_back(elem_pt);
367 Face_index_region_at_boundary[boundary_id - 1]
368 [tmp_region].push_back((j + 2) % 3);
377 Lookup_for_elements_next_boundary_is_setup =
true;
388 template<
class ELEMENT>
405 unsigned n_repeated_ele = 0;
407 const unsigned n_regions = this->nregion();
411 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
420 for (
unsigned rr = 0 ; rr < n_regions; rr++)
422 const unsigned region_id =
423 static_cast<unsigned>(this->Region_attribute[rr]);
426 const unsigned nel_in_region =
427 this->nboundary_element_in_region(b, region_id);
429 unsigned nel_repetead_in_region = 0;
433 if (nel_in_region > 0)
437 bool repeated =
false;
440 for (
unsigned e = 0;
e < nel_in_region;
e++)
444 this->boundary_element_in_region_pt(b, region_id,
e);
448 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
459 this->face_index_at_boundary_in_region(b,region_id,
e);
467 const unsigned n_nodes = tmp_ele_pt->
nnode();
469 std::pair<Node*, Node*> tmp_pair =
470 std::make_pair(tmp_ele_pt->
node_pt(0),
471 tmp_ele_pt->
node_pt(n_nodes - 1));
473 std::pair<Node*, Node*> tmp_pair_inverse =
474 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
478 const unsigned n_done_nodes = done_nodes_pt.size();
479 for (
unsigned l = 0; l < n_done_nodes; l++)
481 if (tmp_pair == done_nodes_pt[l] ||
482 tmp_pair_inverse == done_nodes_pt[l])
484 nel_repetead_in_region++;
494 done_nodes_pt.push_back(tmp_pair);
496 face_el_pt.push_back(tmp_ele_pt);
498 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
512 nele += nel_in_region;
514 n_repeated_ele += nel_repetead_in_region;
523 nele = this->nboundary_element(b);
530 bool repeated =
false;
533 for (
unsigned e = 0;
e < nele;
e++)
540 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
550 int face_index = this->face_index_at_boundary(b,
e);
558 const unsigned n_nodes = tmp_ele_pt->
nnode();
560 std::pair<Node*, Node*> tmp_pair =
561 std::make_pair(tmp_ele_pt->
node_pt(0),
562 tmp_ele_pt->
node_pt(n_nodes - 1));
564 std::pair<Node*, Node*> tmp_pair_inverse =
565 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
569 const unsigned n_done_nodes = done_nodes_pt.size();
570 for (
unsigned l = 0; l < n_done_nodes; l++)
572 if (tmp_pair == done_nodes_pt[l] ||
573 tmp_pair_inverse == done_nodes_pt[l])
587 done_nodes_pt.push_back(tmp_pair);
589 face_el_pt.push_back(tmp_ele_pt);
591 face_to_bulk_element_pt[tmp_ele_pt] = bulk_elem_pt;
609 nele-= n_repeated_ele;
612 if (nele!=face_el_pt.size())
614 std::ostringstream error_message;
616 <<
"The independent counting of face elements ("<<nele<<
") for "
617 <<
"boundary ("<<b<<
") is different\n"
618 <<
"from the real number of face elements in the container ("
619 << face_el_pt.size() <<
")\n";
621 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
622 OOMPH_EXCEPTION_LOCATION);
635 std::vector<bool> is_halo_face_element(nele,
false);
638 unsigned nnon_halo_face_elements = 0;
641 for (
unsigned ie = 0; ie < nele; ie++)
646 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
648 if (!tmp_bulk_ele_pt->
is_halo())
650 is_halo_face_element[ie] =
false;
651 nnon_halo_face_elements++;
656 is_halo_face_element[ie] =
true;
662 const unsigned nhalo_face_element = nele - nnon_halo_face_elements;
663 if (nhalo_face_element > 0)
665 std::ostringstream error_message;
667 <<
"There should not be halo face elements since they were not "
668 <<
"considered when computing the face elements\n\n"
669 <<
"The number of found halo face elements is: "
670 << nhalo_face_element <<
"\n\n";
672 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
673 OOMPH_EXCEPTION_LOCATION);
683 unsigned nsorted_face_elements = 0;
687 std::map<FiniteElement*, bool> done_el;
691 std::map<FiniteElement*, bool> is_inverted;
694 while(nsorted_face_elements < nnon_halo_face_elements)
698 std::list<FiniteElement*> sorted_el_pt;
699 sorted_el_pt.clear();
703 bool found_initial_face_element =
false;
709 for (iface = 0; iface < nele; iface++)
711 if (!is_halo_face_element[iface])
713 ele_face_pt = face_el_pt[iface];
715 if (!done_el[ele_face_pt])
718 found_initial_face_element =
true;
720 nsorted_face_elements++;
722 sorted_el_pt.push_back(ele_face_pt);
724 done_el[ele_face_pt] =
true;
731 if (!found_initial_face_element)
733 std::ostringstream error_message;
735 <<
"Could not find an initial face element for the current segment\n";
737 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
738 OOMPH_EXCEPTION_LOCATION);
743 const unsigned nnod = ele_face_pt->
nnode();
748 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
752 bool face_element_added =
false;
761 for (
unsigned iiface = iface; iiface < nele; iiface++)
764 face_element_added =
false;
767 ele_face_pt = face_el_pt[iiface];
771 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
774 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
775 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
777 if (left_node_pt == local_right_node_pt)
779 left_node_pt = local_left_node_pt;
780 sorted_el_pt.push_front(ele_face_pt);
781 is_inverted[ele_face_pt] =
false;
782 face_element_added =
true;
785 else if (left_node_pt == local_left_node_pt)
787 left_node_pt = local_right_node_pt;
788 sorted_el_pt.push_front(ele_face_pt);
789 is_inverted[ele_face_pt] =
true;
790 face_element_added =
true;
793 else if (right_node_pt == local_left_node_pt)
795 right_node_pt = local_right_node_pt;
796 sorted_el_pt.push_back(ele_face_pt);
797 is_inverted[ele_face_pt] =
false;
798 face_element_added =
true;
801 else if (right_node_pt == local_right_node_pt)
803 right_node_pt = local_left_node_pt;
804 sorted_el_pt.push_back(ele_face_pt);
805 is_inverted[ele_face_pt] =
true;
806 face_element_added =
true;
809 if (face_element_added)
811 done_el[ele_face_pt] =
true;
812 nsorted_face_elements++;
818 }
while(face_element_added &&
819 (nsorted_face_elements < nnon_halo_face_elements));
822 segment_sorted_ele_pt.push_back(sorted_el_pt);
827 const unsigned nsegments = segment_sorted_ele_pt.size();
858 if (nnon_halo_face_elements > 0 && nsegments == 0)
860 std::ostringstream error_message;
862 <<
"The number of segments is zero, but the number of nonhalo\n"
863 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
865 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
866 OOMPH_EXCEPTION_LOCATION);
872 for (
unsigned is = 0; is < nsegments; is++)
875 if (segment_sorted_ele_pt[is].size() == 0)
877 std::ostringstream error_message;
879 <<
"The (" << is <<
")-th segment has no elements\n";
881 "TriangleMesh::identify_boundary_segments_and_assign_initial_zeta_values()",
882 OOMPH_EXCEPTION_LOCATION);
887 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
890 const unsigned nnod = first_ele_pt->
nnode();
894 if (is_inverted[first_ele_pt])
896 first_node_pt = first_ele_pt->node_pt(nnod-1);
900 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
904 if (is_inverted[last_ele_pt])
906 last_node_pt = last_ele_pt->node_pt(0);
910 double x_left = first_node_pt->
x(0);
911 double y_left = first_node_pt->
x(1);
920 if (this->boundary_geom_object_pt(b)!=0)
923 initial_zeta_segment[is] = zeta[0];
925 final_zeta_segment[is] = zeta[0];
929 std::set<Node*> local_nodes_pt;
930 local_nodes_pt.insert(first_node_pt);
933 for (std::list<FiniteElement*>::iterator it =
934 segment_sorted_ele_pt[is].begin();
935 it != segment_sorted_ele_pt[is].end(); it++)
943 if (is_inverted[el_pt])
950 for (
unsigned j = 1; j < nnod; j++)
952 Node* nod_pt = el_pt->node_pt(k_nod);
956 double x_right = nod_pt->
x(0);
957 double y_right = nod_pt->
x(1);
961 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
962 * (y_right - y_left));
979 local_nodes_pt.insert(nod_pt);
985 segment_arclength[is] = zeta[0];
988 nvertices_per_segment[is] = local_nodes_pt.size();
991 segment_all_nodes_pt.push_back(local_nodes_pt);
997 if (segment_all_nodes_pt.size() != nsegments)
999 std::ostringstream error_message;
1001 <<
"The number of segments ("<<nsegments<<
") and the number of "
1002 <<
"sets of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n"
1003 <<
"the\nsegments is different!!!\n\n";
1005 error_message.str(),
1006 OOMPH_CURRENT_FUNCTION,
1007 OOMPH_EXCEPTION_LOCATION);
1035 const unsigned nsegments_initial_coordinates =
1038 const unsigned nsegments_final_coordinates =
1041 if (nsegments_initial_coordinates!=nsegments_final_coordinates)
1043 std::stringstream error_message;
1045 <<
"The number of segments that present initial coordinates "
1046 <<nsegments_initial_coordinates<<
" is different from "
1047 <<
"the\nnumber of segments that present final coordinates "
1048 <<nsegments_final_coordinates<<
"\n\n";
1050 error_message.str(),
1051 OOMPH_CURRENT_FUNCTION,
1052 OOMPH_EXCEPTION_LOCATION);
1057 if (nsegments_initial_coordinates != nsegments)
1059 std::stringstream error_message;
1061 <<
"Working with boundary ("<< b <<
").\n The number of initial and "
1062 <<
"final coordinates ("
1063 <<nsegments_initial_coordinates<<
") is different from\n"
1064 <<
"the number of found segments ("<< nsegments <<
").\n\n";
1066 error_message.str(),
1067 OOMPH_CURRENT_FUNCTION,
1068 OOMPH_EXCEPTION_LOCATION);
1080 Vector<double> original_mesh_segment_initial_arclength(nsegments);
1083 for (
unsigned is = 0; is < nsegments; is++)
1085 original_mesh_segment_initial_coordinate[is].resize(2);
1086 original_mesh_segment_final_coordinate[is].resize(2);
1087 for (
unsigned k = 0; k < 2; k++)
1089 original_mesh_segment_initial_coordinate[is][k] =
1091 original_mesh_segment_final_coordinate[is][k] =
1095 if (this->boundary_geom_object_pt(b)!=0)
1097 original_mesh_segment_initial_zeta[is] =
1099 original_mesh_segment_final_zeta[is] =
1104 original_mesh_segment_initial_arclength[is] =
1106 original_mesh_segment_final_arclength[is] =
1112 Boundary_segment_inverted[b].clear();
1113 Boundary_segment_initial_coordinate[b].clear();
1114 Boundary_segment_final_coordinate[b].clear();
1116 Boundary_segment_initial_zeta[b].clear();
1117 Boundary_segment_final_zeta[b].clear();
1119 Boundary_segment_initial_arclength[b].clear();
1120 Boundary_segment_final_arclength[b].clear();
1126 std::map<unsigned,bool> segment_done;
1127 for (
unsigned is = 0; is < nsegments; is++)
1131 bool found_original_segment =
false;
1140 segment_sorted_ele_pt[is].front();
1143 const unsigned nnod = current_seg_initial_ele_pt->
nnode();
1146 Node *current_seg_first_node_pt=
1147 current_seg_initial_ele_pt->
node_pt(0);
1148 if (is_inverted[current_seg_initial_ele_pt])
1150 current_seg_first_node_pt =
1151 current_seg_initial_ele_pt->node_pt(nnod-1);
1156 segment_sorted_ele_pt[is].back();
1159 Node *current_seg_last_node_pt =
1160 current_seg_last_ele_pt->
node_pt(nnod-1);
1161 if (is_inverted[current_seg_last_ele_pt])
1163 current_seg_last_node_pt =
1164 current_seg_last_ele_pt->node_pt(0);
1168 for (
unsigned i = 0;
i < 2;
i++)
1170 current_seg_initial_coord[
i]=current_seg_first_node_pt->
x(
i);
1171 current_seg_final_coord[
i]=current_seg_last_node_pt->
x(
i);
1178 for (
unsigned orig_s = 0; orig_s < nsegments; orig_s++)
1180 if (!segment_done[orig_s])
1184 original_mesh_segment_initial_coordinate[orig_s];
1186 original_mesh_segment_final_coordinate[orig_s];
1191 ((current_seg_initial_coord[0] - initial_coordinate[0])*
1192 (current_seg_initial_coord[0] - initial_coordinate[0]))
1194 ((current_seg_initial_coord[1] - initial_coordinate[1])*
1195 (current_seg_initial_coord[1] - initial_coordinate[1]));
1205 ((current_seg_final_coord[0] - final_coordinate[0])*
1206 (current_seg_final_coord[0] - final_coordinate[0]))
1208 ((current_seg_final_coord[1] - final_coordinate[1])*
1209 (current_seg_final_coord[1] - final_coordinate[1]));
1219 current_segment_to_original_segment_index[is] = orig_s;
1222 Boundary_segment_inverted[b].push_back(0);
1225 Boundary_segment_initial_coordinate[b].push_back(
1226 initial_coordinate);
1227 Boundary_segment_final_coordinate[b].push_back(
1231 if (this->boundary_geom_object_pt(b)!=0)
1234 Boundary_segment_initial_zeta[b].push_back(
1235 original_mesh_segment_initial_zeta[orig_s]);
1236 Boundary_segment_final_zeta[b].push_back(
1237 original_mesh_segment_final_zeta[orig_s]);
1243 Boundary_segment_initial_arclength[b].push_back(
1244 original_mesh_segment_initial_arclength[orig_s]);
1245 Boundary_segment_final_arclength[b].push_back(
1246 original_mesh_segment_final_arclength[orig_s]);
1249 segment_done[orig_s] =
true;
1251 found_original_segment =
true;
1263 ((current_seg_initial_coord[0] - final_coordinate[0])*
1264 (current_seg_initial_coord[0] - final_coordinate[0]))
1266 ((current_seg_initial_coord[1] - final_coordinate[1])*
1267 (current_seg_initial_coord[1] - final_coordinate[1]));
1268 dist_inv = sqrt(dist_inv);
1278 ((current_seg_final_coord[0] - initial_coordinate[0])*
1279 (current_seg_final_coord[0] - initial_coordinate[0]))
1281 ((current_seg_final_coord[1] - initial_coordinate[1])*
1282 (current_seg_final_coord[1] - initial_coordinate[1]));
1283 dist_inv = sqrt(dist_inv);
1292 current_segment_to_original_segment_index[is] = orig_s;
1295 Boundary_segment_inverted[b].push_back(1);
1298 Boundary_segment_initial_coordinate[b].push_back(
1299 initial_coordinate);
1300 Boundary_segment_final_coordinate[b].push_back(
1304 if (this->boundary_geom_object_pt(b)!=0)
1307 Boundary_segment_initial_zeta[b].push_back(
1308 original_mesh_segment_initial_zeta[orig_s]);
1309 Boundary_segment_final_zeta[b].push_back(
1310 original_mesh_segment_final_zeta[orig_s]);
1315 Boundary_segment_initial_arclength[b].push_back(
1316 original_mesh_segment_initial_arclength[orig_s]);
1317 Boundary_segment_final_arclength[b].push_back(
1318 original_mesh_segment_final_arclength[orig_s]);
1321 segment_done[orig_s] =
true;
1323 found_original_segment =
true;
1338 if (!found_original_segment)
1340 std::stringstream error_message;
1342 <<
"The ("<<is<<
")-th segment on the current segment was not\n"
1343 <<
"found when trying to identify it with the original mesh's\n"
1344 <<
"segment coordinates\n";
1346 OOMPH_CURRENT_FUNCTION,
1347 OOMPH_EXCEPTION_LOCATION);
1368 if (
this != original_mesh_pt)
1381 const double boundary_arclength =
1382 std::max(first_node_zeta_coordinate[0],
1383 last_node_zeta_coordinate[0]);
1385 for (
unsigned is = 0; is < nsegments; is++)
1390 if (boundary_geom_object_pt(b)==0)
1407 FiniteElement* first_ele_pt=segment_sorted_ele_pt[is].front();
1410 const unsigned nnod = first_ele_pt->
nnode();
1414 if (is_inverted[first_ele_pt])
1416 first_node_pt = first_ele_pt->node_pt(nnod-1);
1420 FiniteElement* last_ele_pt=segment_sorted_ele_pt[is].back();
1423 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
1424 if (is_inverted[last_ele_pt])
1426 last_node_pt = last_ele_pt->node_pt(0);
1433 if (!Boundary_segment_inverted[b][is])
1436 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1438 get_coordinates_on_boundary(b, current_segment_final_arclen);
1443 get_coordinates_on_boundary(b, current_segment_final_arclen);
1445 get_coordinates_on_boundary(b, current_segment_initial_arclen);
1453 bool increasing_order =
false;
1457 if (current_segment_initial_arclen[0] <
1458 current_segment_final_arclen[0])
1460 increasing_order =
true;
1464 else if (current_segment_initial_arclen[0] >
1465 current_segment_final_arclen[0])
1467 increasing_order =
false;
1472 std::stringstream error_message;
1474 <<
"It was not possible to identify if the zeta values on "
1475 <<
"boundary ("<<b<<
")\nand segment ("<<is<<
") should go in "
1476 <<
"increasing or decreasing order.\n--- New mesh ---\n"
1477 <<
"Current segment initial arclength: ("
1478 << current_segment_initial_arclen[0]<<
")\n"
1479 <<
"First node coordinates: ("
1480 << first_node_pt->
x(0) <<
", " << first_node_pt->
x(1) <<
")\n"
1481 <<
"Current segment final arclength: ("
1482 << current_segment_final_arclen[0]<<
")\n"
1483 <<
"Last node coordinates: ("
1484 << last_node_pt->
x(0) <<
", " << last_node_pt->
x(1) <<
")\n"
1485 <<
"Current segment arclength: ("
1486 << segment_arclength[is] <<
")\n";
1488 OOMPH_CURRENT_FUNCTION,
1489 OOMPH_EXCEPTION_LOCATION);
1495 const unsigned prev_s =
1496 current_segment_to_original_segment_index[is];
1497 const double original_segment_initial_arclength =
1499 const double original_segment_final_arclength =
1504 bool original_increasing_order =
false;
1509 double starting_arclength = 0.0;
1510 if (original_segment_final_arclength >
1511 original_segment_initial_arclength)
1514 original_increasing_order =
true;
1516 starting_arclength = original_segment_initial_arclength;
1518 else if (original_segment_final_arclength <
1519 original_segment_initial_arclength)
1522 original_increasing_order =
false;
1524 starting_arclength = original_segment_final_arclength;
1529 std::stringstream error_message;
1531 <<
"It was not possible to identify if the zeta values on "
1532 <<
"boundary ("<<b<<
")\nand segment ("<<is<<
") should go in "
1533 <<
"increasing or decreasing order.\n--- Original mesh ---\n"
1534 <<
"Original segment initial arclength: ("
1535 << original_segment_initial_arclength<<
")\n"
1536 <<
"Original segment final arclength: ("
1537 << original_segment_final_arclength<<
")\n";
1539 OOMPH_CURRENT_FUNCTION,
1540 OOMPH_EXCEPTION_LOCATION);
1547 if (increasing_order && original_increasing_order)
1563 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1566 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1567 it != seg_nodes_pt.end(); it++)
1572 Node* nod_pt = (*it);
1577 starting_arclength + (zeta[0] * segment_arclength[is]);
1579 zeta[0] = temp / boundary_arclength;
1581 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1585 else if (std::fabs(zeta[0]) < 1.0e-14)
1594 else if (!increasing_order && original_increasing_order)
1610 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1613 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1614 it != seg_nodes_pt.end(); it++)
1619 Node* nod_pt = (*it);
1624 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1626 zeta[0] = temp / boundary_arclength;
1628 if (std::fabs(zeta[0] - 1.0) < 1.0
e-14)
1632 else if (std::fabs(zeta[0]) < 1.0
e-14)
1640 else if (increasing_order && !original_increasing_order)
1656 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1659 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1660 it != seg_nodes_pt.end(); it++)
1665 Node* nod_pt = (*it);
1670 starting_arclength + ((1.0 - zeta[0]) * segment_arclength[is]);
1672 zeta[0] = temp / boundary_arclength;
1674 if (std::fabs(zeta[0] - 1.0) < 1.0
e-14)
1678 else if (std::fabs(zeta[0]) < 1.0
e-14)
1686 else if (!increasing_order && !original_increasing_order)
1702 std::set<Node*> seg_nodes_pt = segment_all_nodes_pt[is];
1705 for (std::set<Node*>::iterator it = seg_nodes_pt.begin();
1706 it != seg_nodes_pt.end(); it++)
1711 Node* nod_pt = (*it);
1716 starting_arclength + (zeta[0] * segment_arclength[is]);
1718 zeta[0] = temp / boundary_arclength;
1720 if (std::fabs(zeta[0] - 1.0) < 1.0e-14)
1724 else if (std::fabs(zeta[0]) < 1.0e-14)
1736 for (std::list<FiniteElement*>::iterator it_list =
1737 segment_sorted_ele_pt[is].begin();
1738 it_list != segment_sorted_ele_pt[is].end();
1742 const unsigned nnod = (*it_list)->nnode();
1745 Node *first_node_pt = (*it_list)->node_pt(0);
1746 if(is_inverted[(*it_list)])
1748 first_node_pt = (*it_list)->node_pt(nnod-1);
1752 Node *last_node_pt = (*it_list)->node_pt(nnod-1);
1753 if(is_inverted[(*it_list)])
1755 last_node_pt = (*it_list)->node_pt(0);
1761 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1763 std::ostringstream error_message;
1765 <<
"The boundary coordinate of the first node on boundary ("
1766 << b <<
")\nand segment (" << is <<
") is out of the "
1767 <<
"allowed values [0,1]\n"
1768 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1769 <<
"The vertex coordinates are: ("
1770 << first_node_pt->
x(0) <<
", " << first_node_pt->
x(1) <<
")\n";
1772 OOMPH_CURRENT_FUNCTION,
1773 OOMPH_EXCEPTION_LOCATION);
1778 if (zeta[0] < 0.0 || zeta[0] > 1.0)
1780 std::ostringstream error_message;
1782 <<
"The boundary coordinate of the last node on boundary ("
1783 << b <<
")\nand segment (" << is <<
") is out of the "
1784 <<
"allowed values [0,1]\n"
1785 <<
"The node boundary coordinate: (" << zeta[0] <<
")\n"
1786 <<
"The vertex coordinates are: ("
1787 << last_node_pt->
x(0) <<
", " << last_node_pt->
x(1) <<
")\n";
1789 OOMPH_CURRENT_FUNCTION,
1790 OOMPH_EXCEPTION_LOCATION);
1793 #endif // #ifdef PARANOID
1809 Boundary_initial_coordinate[b] =
1812 Boundary_final_coordinate[b] =
1817 Boundary_initial_zeta_coordinate[b] =
1820 Boundary_final_zeta_coordinate[b] =
1827 Assigned_segments_initial_zeta_values[b] =
true;
1830 for (
unsigned i = 0;
i < nele;
i++)
1832 delete face_el_pt[
i];
1844 template<
class ELEMENT>
1857 const unsigned nproc = comm_pt->nproc();
1859 const unsigned my_rank = comm_pt->my_rank();
1867 bool is_internal_boundary =
false;
1871 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
1875 select_boundary_face_elements(all_face_ele_pt, b, is_internal_boundary,
1876 face_to_bulk_element_pt);
1879 const unsigned n_all_face_ele = all_face_ele_pt.size();
1887 std::vector<bool> is_halo_face_element(n_all_face_ele,
false);
1890 unsigned nnon_halo_face_elements = 0;
1894 for (
unsigned ie = 0; ie < n_all_face_ele; ie++)
1898 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_ele_pt];
1900 if (!tmp_bulk_ele_pt->
is_halo())
1903 is_halo_face_element[ie] =
false;
1905 nnon_halo_face_elements++;
1910 is_halo_face_element[ie] =
true;
1916 const unsigned nhalo_face_element = n_all_face_ele - nnon_halo_face_elements;
1924 unsigned nsorted_face_elements = 0;
1928 std::map<FiniteElement*, bool> done_el;
1932 std::map<FiniteElement*, bool> is_inverted;
1935 while(nsorted_face_elements < nnon_halo_face_elements)
1939 std::list<FiniteElement*> sorted_el_pt;
1940 sorted_el_pt.clear();
1945 bool found_initial_face_element =
false;
1951 for (iface = 0; iface < n_all_face_ele; iface++)
1953 if (!is_halo_face_element[iface])
1955 ele_face_pt = all_face_ele_pt[iface];
1957 if (!done_el[ele_face_pt])
1960 found_initial_face_element =
true;
1962 nsorted_face_elements++;
1964 sorted_el_pt.push_back(ele_face_pt);
1966 done_el[ele_face_pt] =
true;
1973 if (!found_initial_face_element)
1975 std::ostringstream error_message;
1977 <<
"Could not find an initial face element for the current segment\n";
1980 OOMPH_CURRENT_FUNCTION,
1981 OOMPH_EXCEPTION_LOCATION);
1986 const unsigned nnod = ele_face_pt->
nnode();
1991 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
1995 bool face_element_added =
false;
2004 for (
unsigned iiface = iface; iiface < n_all_face_ele; iiface++)
2007 face_element_added =
false;
2010 ele_face_pt = all_face_ele_pt[iiface];
2014 if (!(done_el[ele_face_pt] || is_halo_face_element[iiface]))
2017 Node* local_left_node_pt = ele_face_pt->
node_pt(0);
2018 Node* local_right_node_pt = ele_face_pt->
node_pt(nnod - 1);
2021 if (left_node_pt == local_right_node_pt)
2023 left_node_pt = local_left_node_pt;
2024 sorted_el_pt.push_front(ele_face_pt);
2025 is_inverted[ele_face_pt] =
false;
2026 face_element_added =
true;
2029 else if (left_node_pt == local_left_node_pt)
2031 left_node_pt = local_right_node_pt;
2032 sorted_el_pt.push_front(ele_face_pt);
2033 is_inverted[ele_face_pt] =
true;
2034 face_element_added =
true;
2037 else if (right_node_pt == local_left_node_pt)
2039 right_node_pt = local_right_node_pt;
2040 sorted_el_pt.push_back(ele_face_pt);
2041 is_inverted[ele_face_pt] =
false;
2042 face_element_added =
true;
2045 else if (right_node_pt == local_right_node_pt)
2047 right_node_pt = local_left_node_pt;
2048 sorted_el_pt.push_back(ele_face_pt);
2049 is_inverted[ele_face_pt] =
true;
2050 face_element_added =
true;
2053 if (face_element_added)
2055 done_el[ele_face_pt] =
true;
2056 nsorted_face_elements++;
2062 }
while(face_element_added &&
2063 (nsorted_face_elements < nnon_halo_face_elements));
2066 segment_sorted_ele_pt.push_back(sorted_el_pt);
2083 const unsigned nsegments = segment_sorted_ele_pt.size();
2087 if (nnon_halo_face_elements > 0 && nsegments == 0)
2089 std::ostringstream error_message;
2091 <<
"The number of segments is zero, but the number of nonhalo\n"
2092 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
2094 OOMPH_CURRENT_FUNCTION,
2095 OOMPH_EXCEPTION_LOCATION);
2114 for (
unsigned is = 0; is < nsegments; is++)
2117 if (segment_sorted_ele_pt[is].size() == 0)
2119 std::ostringstream error_message;
2121 <<
"The (" << is <<
")-th segment has no elements\n";
2123 OOMPH_CURRENT_FUNCTION,
2124 OOMPH_EXCEPTION_LOCATION);
2129 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2132 const unsigned nnod = first_ele_pt->
nnode();
2136 if (is_inverted[first_ele_pt])
2138 first_node_pt = first_ele_pt->node_pt(nnod-1);
2142 double x_left = first_node_pt->
x(0);
2143 double y_left = first_node_pt->
x(1);
2152 if (this->boundary_geom_object_pt(b)!=0)
2157 initial_zeta_segment[is] = zeta[0];
2160 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2163 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
2164 if (is_inverted[last_ele_pt])
2166 last_node_pt = last_ele_pt->node_pt(0);
2172 final_zeta_segment[is] = zeta[0];
2178 std::set<Node*> local_nodes_pt;
2180 local_nodes_pt.insert(first_node_pt);
2183 for (std::list<FiniteElement*>::iterator it =
2184 segment_sorted_ele_pt[is].begin();
2185 it != segment_sorted_ele_pt[is].end(); it++)
2194 if (is_inverted[el_pt])
2201 for (
unsigned j = 1; j < nnod; j++)
2203 Node* nod_pt = el_pt->node_pt(k_nod);
2207 double x_right = nod_pt->
x(0);
2208 double y_right = nod_pt->
x(1);
2212 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
2213 * (y_right - y_left));
2230 local_nodes_pt.insert(nod_pt);
2239 segment_arclength[is] = zeta[0];
2244 nvertices_per_segment[is] = local_nodes_pt.size();
2247 segment_all_nodes_pt.push_back(local_nodes_pt);
2269 unsigned proc_with_initial_seg = 0;
2270 unsigned proc_with_final_seg = 0;
2274 unsigned initial_segment = 0;
2275 unsigned final_segment = 0;
2284 for (
unsigned is = 0; is < nsegments; is++)
2286 for (std::list<FiniteElement*>::iterator it_seg =
2287 segment_sorted_ele_pt[is].begin();
2288 it_seg != segment_sorted_ele_pt[is].end();
2291 segment_sorted_nonhalo_ele_pt[is].push_back((*it_seg));
2298 for (
unsigned is = 0; is < nsegments; is++)
2301 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
2304 const unsigned nnod = first_ele_pt->
nnode();
2308 if (is_inverted[first_ele_pt])
2310 first_node_pt = first_ele_pt->node_pt(nnod-1);
2314 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
2317 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
2318 if (is_inverted[last_ele_pt])
2320 last_node_pt = last_ele_pt->node_pt(0);
2327 bool attached_left_halo =
false;
2328 bool attached_right_halo =
false;
2329 if (nhalo_face_element > 0)
2331 for (
unsigned iiface = 0; iiface < n_all_face_ele; iiface++)
2347 if (is_halo_face_element[iiface])
2350 Node* left_node_pt = halo_face_ele_pt->
node_pt(0);
2351 Node* right_node_pt = halo_face_ele_pt->
node_pt(nnod-1);
2353 if (!attached_left_halo && (first_node_pt == right_node_pt ||
2354 first_node_pt == left_node_pt))
2357 segment_sorted_ele_pt[is].push_front(halo_face_ele_pt);
2361 attached_left_halo =
true;
2364 else if (!attached_right_halo && (last_node_pt == left_node_pt ||
2365 last_node_pt == right_node_pt))
2368 segment_sorted_ele_pt[is].push_back(halo_face_ele_pt);
2371 attached_right_halo =
true;
2375 if (attached_left_halo && attached_right_halo)
2425 for (
unsigned is = 0; is < nsegments; is++)
2428 FiniteElement* left_face_ele_pt=segment_sorted_ele_pt[is].front();
2433 face_to_bulk_element_pt[left_face_ele_pt];
2436 if (tmp_left_bulk_ele_pt->
is_halo())
2443 std::ostringstream error_message;
2445 <<
"The current bulk element (left) is marked as halo but "
2446 <<
"the processor holding\nthe non-halo counterpart is "
2449 OOMPH_CURRENT_FUNCTION,
2450 OOMPH_EXCEPTION_LOCATION);
2454 unsigned left_processor =
static_cast<unsigned>(left_proc);
2455 left_processor_plus_one[is] = left_processor + 1;
2462 this->halo_element_pt(left_processor);
2466 bool left_halo_element_found =
false;
2469 const unsigned n_halo_left = left_halo_element_pt.size();
2470 for (
unsigned lh = 0; lh < n_halo_left; lh++)
2472 if (left_element_pt == left_halo_element_pt[lh])
2474 left_halo_element[is] = lh;
2476 left_halo_element_found =
true;
2483 if (!left_halo_element_found)
2485 std::ostringstream error_message;
2487 <<
"The current bulk element (left) marked as halo was "
2488 <<
"not found in the vector of halo\nelements associated "
2489 <<
"with the (" << left_processor <<
") processor.\n\n";
2491 OOMPH_CURRENT_FUNCTION,
2492 OOMPH_EXCEPTION_LOCATION);
2498 left_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].front();
2501 tmp_left_bulk_ele_pt = face_to_bulk_element_pt[left_face_ele_pt];
2505 if (tmp_left_bulk_ele_pt->
is_halo())
2507 std::ostringstream error_message;
2509 <<
"The bulk element represetation of the left-most nonhalo face\n"
2510 <<
"element of the current segment ("<<is<<
") is marked as halo,\n"
2511 <<
"but the face element created from it is nonhalo\n";
2513 OOMPH_CURRENT_FUNCTION,
2514 OOMPH_EXCEPTION_LOCATION);
2520 left_element_pt = tmp_left_bulk_ele_pt;
2524 bool left_haloed_element_found =
false;
2530 this->haloed_element_pt(left_processor);
2532 const unsigned nhaloed_left = left_haloed_element_pt.size();
2533 for (
unsigned lhd = 0; lhd < nhaloed_left; lhd++)
2535 if (left_element_pt == left_haloed_element_pt[lhd])
2537 left_haloed_element[is] = lhd;
2539 left_haloed_element_found =
true;
2546 if (!left_haloed_element_found)
2548 std::ostringstream error_message;
2550 <<
"The current bulk element (left) marked as haloed was "
2551 <<
"not found in the vector of haloed\nelements associated "
2552 <<
"with processor ("<< left_processor <<
").\n";
2554 OOMPH_CURRENT_FUNCTION,
2555 OOMPH_EXCEPTION_LOCATION);
2562 left_processor_plus_one[is] = 0;
2564 left_halo_element[is] = 0;
2566 left_haloed_element[is] = 0;
2570 FiniteElement* right_face_ele_pt = segment_sorted_ele_pt[is].back();
2575 face_to_bulk_element_pt[right_face_ele_pt];
2578 if (tmp_right_bulk_ele_pt->
is_halo())
2585 std::ostringstream error_message;
2587 <<
"The current bulk element (right) is marked as halo but "
2588 <<
"the processor holding\nthe non-halo counterpart is "
2591 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2592 OOMPH_EXCEPTION_LOCATION);
2596 unsigned right_processor =
static_cast<unsigned>(right_proc);
2597 right_processor_plus_one[is] = right_processor + 1;
2604 this->halo_element_pt(right_processor);
2608 bool right_halo_element_found =
false;
2611 const unsigned nhalo_right = right_halo_element_pt.size();
2612 for (
unsigned rh = 0; rh < nhalo_right; rh++)
2614 if (right_element_pt == right_halo_element_pt[rh])
2616 right_halo_element[is] = rh;
2618 right_halo_element_found =
true;
2624 if (!right_halo_element_found)
2626 std::ostringstream error_message;
2628 <<
"The current bulk element (right) marked as halo was not "
2629 <<
"found in the vector of halo\nelements associated with "
2630 <<
"the (" << right_processor <<
") processor.\n\n";
2632 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2633 OOMPH_EXCEPTION_LOCATION);
2639 right_face_ele_pt = segment_sorted_nonhalo_ele_pt[is].back();
2642 tmp_right_bulk_ele_pt=face_to_bulk_element_pt[right_face_ele_pt];
2645 if (tmp_right_bulk_ele_pt->
is_halo())
2647 std::ostringstream error_message;
2649 <<
"The bulk element represetation of the right-most nonhalo face\n"
2650 <<
"element of the current segment ("<<is<<
") is marked as halo,\n"
2651 <<
"but the face element created from it is nonhalo\n";
2653 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2654 OOMPH_EXCEPTION_LOCATION);
2660 right_element_pt = tmp_right_bulk_ele_pt;
2664 bool right_haloed_element_found =
false;
2669 this->haloed_element_pt(right_processor);
2671 const unsigned nhaloed_right = right_haloed_element_pt.size();
2672 for (
unsigned rhd = 0; rhd < nhaloed_right; rhd++)
2674 if (right_element_pt == right_haloed_element_pt[rhd])
2676 right_haloed_element[is] = rhd;
2678 right_haloed_element_found =
true;
2685 if (!right_haloed_element_found)
2687 std::ostringstream error_message;
2689 <<
"The current bulk element (right) marked as haloed was not "
2690 <<
"found in the vector of haloed\nelements associated with "
2691 <<
"the ("<< right_processor <<
") processor.\n\n";
2693 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
2694 OOMPH_EXCEPTION_LOCATION);
2702 right_processor_plus_one[is] = 0;
2704 right_halo_element[is] = 0;
2706 right_haloed_element[is] = 0;
2722 const unsigned root_processor = 0;
2729 unsigned nsegments_mpi = nsegments;
2730 MPI_Gather(&nsegments_mpi, 1, MPI_UNSIGNED,
2731 &root_nsegments_per_processor[0], 1, MPI_UNSIGNED,
2732 root_processor, comm_pt->mpi_comm());
2740 const unsigned spu = 7;
2742 for (
unsigned is = 0; is < nsegments; is++)
2744 flat_packed_unsigned_send_data[(spu*is)+0]=left_processor_plus_one[is];
2745 flat_packed_unsigned_send_data[(spu*is)+1]=right_processor_plus_one[is];
2746 flat_packed_unsigned_send_data[(spu*is)+2]=left_halo_element[is];
2747 flat_packed_unsigned_send_data[(spu*is)+3]=right_halo_element[is];
2748 flat_packed_unsigned_send_data[(spu*is)+4]=left_haloed_element[is];
2749 flat_packed_unsigned_send_data[(spu*is)+5]=right_haloed_element[is];
2750 flat_packed_unsigned_send_data[(spu*is)+6]=nvertices_per_segment[is];
2754 const unsigned nudata_to_send = flat_packed_unsigned_send_data.size();
2760 unsigned root_nutotal_data_receive = 0;
2761 for (
unsigned ip = 0; ip < nproc; ip++)
2765 root_nudata_to_receive[ip] = root_nsegments_per_processor[ip] * spu;
2767 root_nutotal_data_receive+= root_nudata_to_receive[ip];
2773 root_uoffsets_receive[0] = 0;
2774 for (
unsigned ip = 1; ip < nproc; ip++)
2777 root_uoffsets_receive[ip] =
2778 root_uoffsets_receive[ip-1] + root_nudata_to_receive[ip-1];
2782 if (flat_packed_unsigned_send_data.size()==0)
2784 flat_packed_unsigned_send_data.resize(1);
2789 root_nutotal_data_receive);
2790 if (my_rank!=root_processor)
2793 if (flat_packed_unsigned_receive_data.size()==0)
2795 flat_packed_unsigned_receive_data.resize(1);
2799 MPI_Gatherv(&flat_packed_unsigned_send_data[0],
2805 &flat_packed_unsigned_receive_data[0],
2810 &root_nudata_to_receive[0],
2812 &root_uoffsets_receive[0],
2817 comm_pt->mpi_comm());
2820 flat_packed_unsigned_send_data.clear();
2821 flat_packed_unsigned_send_data.resize(0);
2827 const unsigned spd = 1;
2829 for (
unsigned is = 0; is < nsegments; is++)
2831 flat_packed_double_send_data[(spd*is)+0]=segment_arclength[is];
2835 const unsigned nddata_to_send = flat_packed_double_send_data.size();
2840 unsigned root_ndtotal_data_receive = 0;
2841 for (
unsigned ip =0; ip < nproc; ip++)
2843 root_nddata_to_receive[ip] = root_nsegments_per_processor[ip] * spd;
2844 root_ndtotal_data_receive+= root_nddata_to_receive[ip];
2850 root_doffsets_receive[0] = 0;
2851 for (
unsigned ip = 1; ip < nproc; ip++)
2854 root_doffsets_receive[ip] =
2855 root_doffsets_receive[ip-1] + root_nddata_to_receive[ip-1];
2859 if (flat_packed_double_send_data.size()==0)
2861 flat_packed_double_send_data.resize(1);
2865 Vector<double> flat_packed_double_receive_data(root_ndtotal_data_receive);
2866 if (my_rank!=root_processor)
2869 if (flat_packed_double_receive_data.size()==0)
2871 flat_packed_double_receive_data.resize(1);
2875 MPI_Gatherv(&flat_packed_double_send_data[0],
2881 &flat_packed_double_receive_data[0],
2885 &root_nddata_to_receive[0],
2887 &root_doffsets_receive[0],
2892 comm_pt->mpi_comm());
2895 flat_packed_double_send_data.clear();
2896 flat_packed_double_send_data.resize(0);
2918 double root_accumulated_arclength = 0.0;
2922 unsigned root_accumulated_vertices_before_segment = 0;
2926 if (my_rank == root_processor)
2972 unsigned ucounter = 0;
2973 unsigned dcounter = 0;
2974 for (
unsigned ip = 0; ip < nproc; ip++)
2977 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
2979 root_left_processor_plus_one[ip].resize(nsegs_iproc);
2980 root_right_processor_plus_one[ip].resize(nsegs_iproc);
2981 root_left_halo_element[ip].resize(nsegs_iproc);
2982 root_right_halo_element[ip].resize(nsegs_iproc);
2983 root_left_haloed_element[ip].resize(nsegs_iproc);
2984 root_right_haloed_element[ip].resize(nsegs_iproc);
2987 root_nvertices_per_segment[ip].resize(nsegs_iproc);
2988 root_segment_arclength[ip].resize(nsegs_iproc);
2989 root_segment_inverted[ip].resize(nsegs_iproc);
2993 for(
unsigned is = 0; is < nsegs_iproc; is++)
2996 root_left_processor_plus_one[ip][is] =
2997 flat_packed_unsigned_receive_data[ucounter++];
2998 root_right_processor_plus_one[ip][is] =
2999 flat_packed_unsigned_receive_data[ucounter++];
3000 root_left_halo_element[ip][is] =
3001 flat_packed_unsigned_receive_data[ucounter++];
3002 root_right_halo_element[ip][is] =
3003 flat_packed_unsigned_receive_data[ucounter++];
3004 root_left_haloed_element[ip][is] =
3005 flat_packed_unsigned_receive_data[ucounter++];
3006 root_right_haloed_element[ip][is] =
3007 flat_packed_unsigned_receive_data[ucounter++];
3008 root_nvertices_per_segment[ip][is] =
3009 flat_packed_unsigned_receive_data[ucounter++];
3012 root_segment_arclength[ip][is] =
3013 flat_packed_double_receive_data[dcounter++];
3024 for (
unsigned ip = 0; ip < nproc; ip++)
3026 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3027 left_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3028 right_connected_segment_plus_one[ip].resize(nsegs_iproc,-1);
3033 std::list<std::pair<unsigned, unsigned> > proc_seg_connectivity;
3034 proc_seg_connectivity.clear();
3037 std::map<std::pair<unsigned, unsigned>,
bool> done_segment;
3041 unsigned left_proc = 0;
3042 unsigned right_proc = 0;
3043 unsigned left_seg = 0;
3044 unsigned right_seg = 0;
3045 for (
unsigned ip = 0; ip < nproc; ip++)
3047 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3048 if (nsegs_iproc > 0)
3050 right_proc = left_proc = ip;
3051 right_seg = left_seg = 0;
3058 std::pair<unsigned, unsigned> add_segment =
3059 std::make_pair(left_proc, left_seg);
3060 done_segment[add_segment] =
true;
3061 proc_seg_connectivity.push_back(add_segment);
3065 bool added_segment_to_the_left =
false;
3066 bool added_segment_to_the_right =
false;
3071 std::pair<unsigned, unsigned> left_pair =
3072 proc_seg_connectivity.front();
3073 left_proc = left_pair.first;
3074 left_seg = left_pair.second;
3078 const unsigned new_left_proc =
3079 root_left_processor_plus_one[left_proc][left_seg];
3081 if (new_left_proc != 0)
3084 added_segment_to_the_left =
false;
3086 const unsigned left_halo_id =
3087 root_left_halo_element[left_proc][left_seg];
3090 const unsigned left_haloed_id =
3091 root_left_haloed_element[left_proc][left_seg];
3095 const unsigned nsegs_new_left_proc =
3096 root_nsegments_per_processor[new_left_proc-1];
3098 for (
unsigned ils = 0; ils < nsegs_new_left_proc; ils++)
3100 std::pair<unsigned, unsigned> candidate_seg =
3101 std::make_pair(new_left_proc-1, ils);
3104 if (!done_segment[candidate_seg])
3108 const unsigned right_proc_of_new_left_proc =
3109 root_right_processor_plus_one[new_left_proc-1][ils];
3112 const unsigned left_proc_of_new_left_proc =
3113 root_left_processor_plus_one[new_left_proc-1][ils];
3116 if (right_proc_of_new_left_proc != 0 &&
3117 right_proc_of_new_left_proc-1 == left_proc)
3122 const unsigned right_halo_id =
3123 root_right_halo_element[new_left_proc-1][ils];
3124 const unsigned right_haloed_id =
3125 root_right_haloed_element[new_left_proc-1][ils];
3126 if (left_halo_id == right_haloed_id &&
3127 left_haloed_id == right_halo_id)
3131 left_connected_segment_plus_one[left_proc][left_seg]=
3134 proc_seg_connectivity.push_front(candidate_seg);
3135 added_segment_to_the_left =
true;
3141 if (left_proc_of_new_left_proc != 0 &&
3142 left_proc_of_new_left_proc-1 == left_proc)
3147 const unsigned inv_left_halo_id =
3148 root_left_halo_element[new_left_proc-1][ils];
3149 const unsigned inv_left_haloed_id =
3150 root_left_haloed_element[new_left_proc-1][ils];
3151 if (left_halo_id == inv_left_haloed_id &&
3152 left_haloed_id == inv_left_halo_id)
3156 left_connected_segment_plus_one[left_proc][left_seg]=
3159 proc_seg_connectivity.push_front(candidate_seg);
3163 const unsigned tmp_proc =
3164 root_left_processor_plus_one[new_left_proc-1][ils];
3165 const unsigned tmp_halo =
3166 root_left_halo_element[new_left_proc-1][ils];
3167 const unsigned tmp_haloed =
3168 root_left_haloed_element[new_left_proc-1][ils];
3170 root_left_processor_plus_one[new_left_proc-1][ils] =
3171 root_right_processor_plus_one[new_left_proc-1][ils];
3172 root_left_halo_element[new_left_proc-1][ils] =
3173 root_right_halo_element[new_left_proc-1][ils];
3174 root_left_haloed_element[new_left_proc-1][ils] =
3175 root_right_haloed_element[new_left_proc-1][ils];
3177 root_right_processor_plus_one[new_left_proc-1][ils] =
3179 root_right_halo_element[new_left_proc-1][ils]=tmp_halo;
3180 root_right_haloed_element[new_left_proc-1][ils] =
3185 root_segment_inverted[new_left_proc-1][ils] = 1;
3187 added_segment_to_the_left =
true;
3195 if (!added_segment_to_the_left)
3197 std::ostringstream error_message;
3199 <<
"The corresponding processor and segment to the left of "
3200 <<
"the current left\nmost segment was not found\n";
3202 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3203 OOMPH_EXCEPTION_LOCATION);
3210 added_segment_to_the_left =
false;
3214 std::pair<unsigned, unsigned> right_pair =
3215 proc_seg_connectivity.back();
3216 right_proc = right_pair.first;
3217 right_seg = right_pair.second;
3221 const unsigned new_right_proc =
3222 root_right_processor_plus_one[right_proc][right_seg];
3224 if (new_right_proc != 0)
3227 added_segment_to_the_right =
false;
3229 const unsigned right_halo_id =
3230 root_right_halo_element[right_proc][right_seg];
3233 const unsigned right_haloed_id =
3234 root_right_haloed_element[right_proc][right_seg];
3238 const unsigned nsegs_new_right_proc =
3239 root_nsegments_per_processor[new_right_proc-1];
3241 for (
unsigned irs = 0; irs < nsegs_new_right_proc; irs++)
3243 std::pair<unsigned, unsigned> candidate_seg =
3244 std::make_pair(new_right_proc-1, irs);
3247 if (!done_segment[candidate_seg])
3251 const unsigned left_proc_of_new_right_proc =
3252 root_left_processor_plus_one[new_right_proc-1][irs];
3255 const unsigned right_proc_of_new_right_proc =
3256 root_right_processor_plus_one[new_right_proc-1][irs];
3259 if (left_proc_of_new_right_proc != 0 &&
3260 left_proc_of_new_right_proc-1 == right_proc)
3265 const unsigned left_halo_id =
3266 root_left_halo_element[new_right_proc-1][irs];
3267 const unsigned left_haloed_id =
3268 root_left_haloed_element[new_right_proc-1][irs];
3270 if (right_halo_id == left_haloed_id &&
3271 right_haloed_id == left_halo_id)
3275 right_connected_segment_plus_one[right_proc][right_seg]=
3278 proc_seg_connectivity.push_back(candidate_seg);
3279 added_segment_to_the_right =
true;
3285 if (right_proc_of_new_right_proc != 0 &&
3286 right_proc_of_new_right_proc-1 == right_proc)
3292 const unsigned inv_right_halo_id =
3293 root_right_halo_element[new_right_proc-1][irs];
3294 const unsigned inv_right_haloed_id =
3295 root_right_haloed_element[new_right_proc-1][irs];
3296 if (right_halo_id == inv_right_haloed_id &&
3297 right_haloed_id == inv_right_halo_id)
3301 right_connected_segment_plus_one[right_proc][right_seg]=
3304 proc_seg_connectivity.push_back(candidate_seg);
3307 const unsigned tmp_proc =
3308 root_left_processor_plus_one[new_right_proc-1][irs];
3309 const unsigned tmp_halo =
3310 root_left_halo_element[new_right_proc-1][irs];
3311 const unsigned tmp_haloed =
3312 root_left_haloed_element[new_right_proc-1][irs];
3314 root_left_processor_plus_one[new_right_proc-1][irs] =
3315 root_right_processor_plus_one[new_right_proc-1][irs];
3316 root_left_halo_element[new_right_proc-1][irs] =
3317 root_right_halo_element[new_right_proc-1][irs];
3318 root_left_haloed_element[new_right_proc-1][irs] =
3319 root_right_haloed_element[new_right_proc-1][irs];
3321 root_right_processor_plus_one[new_right_proc-1][irs] =
3323 root_right_halo_element[new_right_proc-1][irs]=tmp_halo;
3324 root_right_haloed_element[new_right_proc-1][irs] =
3329 root_segment_inverted[new_right_proc-1][irs] = 1;
3331 added_segment_to_the_right =
true;
3339 if (!added_segment_to_the_right)
3341 std::ostringstream error_message;
3343 <<
"The corresponding processor and segment to the right of "
3344 <<
"the current right\nmost segment was not found\n";
3346 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3347 OOMPH_EXCEPTION_LOCATION);
3354 added_segment_to_the_right =
false;
3357 }
while(added_segment_to_the_left || added_segment_to_the_right);
3365 const unsigned ntotal_segments = proc_seg_connectivity.size();
3367 unsigned tmp_total_segments = 0;
3368 for (
unsigned ip =0; ip < nproc; ip++)
3370 tmp_total_segments+= root_nsegments_per_processor[ip];
3375 if (ntotal_segments!=tmp_total_segments)
3377 std::ostringstream error_message;
3379 <<
"The number of sorted segments (" << ntotal_segments <<
") on "
3380 <<
"boundary ("<< b <<
")\nis different from the total number of "
3381 <<
"segments ("<< tmp_total_segments <<
") in all\nprocessors.\n\n";
3383 OOMPH_CURRENT_FUNCTION,
3384 OOMPH_EXCEPTION_LOCATION);
3393 for (
unsigned ip = 0; ip < nproc; ip++)
3395 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3396 root_initial_segment_arclength[ip].resize(nsegs_iproc);
3397 root_nvertices_before_segment[ip].resize(nsegs_iproc);
3404 for (std::list<std::pair<unsigned, unsigned> >::iterator
3405 it_list = proc_seg_connectivity.begin();
3406 it_list != proc_seg_connectivity.end(); it_list++)
3408 const unsigned iproc =
static_cast<unsigned>((*it_list).first);
3409 const unsigned iseg =
static_cast<unsigned>((*it_list).second);
3410 const double iseg_arclength = root_segment_arclength[iproc][iseg];
3411 const unsigned iseg_nvertices = root_nvertices_per_segment[iproc][iseg];
3413 aux_initial_segment_arclength[ucounter] = root_accumulated_arclength;
3414 aux_nvertices_before_segment[ucounter] =
3415 root_accumulated_vertices_before_segment;
3418 root_initial_segment_arclength[iproc][iseg] = root_accumulated_arclength;
3420 root_nvertices_before_segment[iproc][iseg] =
3421 root_accumulated_vertices_before_segment;
3424 root_accumulated_arclength+= iseg_arclength;
3426 root_accumulated_vertices_before_segment+= iseg_nvertices - 1;
3435 root_accumulated_vertices_before_segment++;
3438 proc_with_initial_seg = proc_seg_connectivity.front().first;
3439 proc_with_final_seg = proc_seg_connectivity.back().first;
3442 initial_segment = proc_seg_connectivity.front().second;
3443 final_segment = proc_seg_connectivity.back().second;
3448 unsigned root_ntotal_segments = 0;
3449 for (
unsigned ip =0; ip < nproc; ip++)
3451 root_ntotal_segments+= root_nsegments_per_processor[ip];
3458 const unsigned rspu = 2;
3459 flat_packed_unsigned_send_data.clear();
3460 flat_packed_unsigned_send_data.resize(root_ntotal_segments*rspu);
3461 unsigned ucounter = 0;
3463 for (
unsigned ip = 0; ip < nproc; ip++)
3465 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3466 for (
unsigned is = 0; is < nsegs_iproc; is++)
3468 flat_packed_unsigned_send_data[ucounter++] =
3469 root_nvertices_before_segment[ip][is];
3470 flat_packed_unsigned_send_data[ucounter++] =
3471 root_segment_inverted[ip][is];
3477 for (
unsigned ip =0; ip < nproc; ip++)
3480 root_nudata_to_send[ip] = root_nsegments_per_processor[ip] * rspu;
3485 root_uoffsets_send[0] = 0;
3486 for (
unsigned ip = 1; ip < nproc; ip++)
3489 root_uoffsets_send[ip] =
3490 root_uoffsets_send[ip-1] + root_nudata_to_send[ip-1];
3494 unsigned nutotal_data_receive = nsegments * rspu;
3496 if (my_rank!=root_processor)
3499 if (flat_packed_unsigned_send_data.size()==0)
3501 flat_packed_unsigned_send_data.resize(1);
3506 flat_packed_unsigned_receive_data.clear();
3507 flat_packed_unsigned_receive_data.resize(nutotal_data_receive);
3509 if (flat_packed_unsigned_receive_data.size()==0)
3511 flat_packed_unsigned_receive_data.resize(1);
3514 MPI_Scatterv(&flat_packed_unsigned_send_data[0],
3515 &root_nudata_to_send[0],
3516 &root_uoffsets_send[0],
3518 &flat_packed_unsigned_receive_data[0],
3519 nutotal_data_receive,
3522 comm_pt->mpi_comm());
3527 const unsigned rspd = 1;
3528 flat_packed_double_send_data.clear();
3529 flat_packed_double_send_data.resize(root_ntotal_segments*rspd);
3530 unsigned dcounter = 0;
3532 for (
unsigned ip = 0; ip < nproc; ip++)
3534 const unsigned nsegs_iproc = root_nsegments_per_processor[ip];
3535 for (
unsigned is = 0; is < nsegs_iproc; is++)
3537 flat_packed_double_send_data[dcounter++] =
3538 root_initial_segment_arclength[ip][is];
3544 for (
unsigned ip =0; ip < nproc; ip++)
3547 root_nddata_to_send[ip] = root_nsegments_per_processor[ip] * rspd;
3552 root_doffsets_send[0] = 0;
3553 for (
unsigned ip = 1; ip < nproc; ip++)
3556 root_doffsets_send[ip] =
3557 root_doffsets_send[ip-1] + root_nddata_to_send[ip-1];
3561 unsigned ndtotal_data_receive = nsegments * rspd;
3563 if (my_rank!=root_processor)
3566 if (flat_packed_double_send_data.size()==0)
3568 flat_packed_double_send_data.resize(1);
3573 flat_packed_double_receive_data.clear();
3574 flat_packed_double_receive_data.resize(ndtotal_data_receive);
3576 if (flat_packed_double_receive_data.size()==0)
3578 flat_packed_double_receive_data.resize(1);
3581 MPI_Scatterv(&flat_packed_double_send_data[0],
3582 &root_nddata_to_send[0],
3583 &root_doffsets_send[0],
3585 &flat_packed_double_receive_data[0],
3586 ndtotal_data_receive,
3589 comm_pt->mpi_comm());
3598 for (
unsigned is = 0; is < nsegments; is++)
3601 nvertices_before_segment[is] =
3602 flat_packed_unsigned_receive_data[ucounter++];
3604 segment_inverted[is] = flat_packed_unsigned_receive_data[ucounter++];
3606 initial_segment_arclength[is] =
3607 flat_packed_double_receive_data[dcounter++];
3613 const unsigned numore_info = 5;
3616 flat_package_unsigned_more_info[0] = root_accumulated_vertices_before_segment;
3617 flat_package_unsigned_more_info[1] = proc_with_initial_seg;
3618 flat_package_unsigned_more_info[2] = proc_with_final_seg;
3619 flat_package_unsigned_more_info[3] = initial_segment;
3620 flat_package_unsigned_more_info[4] = final_segment;
3623 MPI_Bcast(&flat_package_unsigned_more_info[0], numore_info,
3624 MPI_UNSIGNED, root_processor, comm_pt->mpi_comm());
3627 root_accumulated_vertices_before_segment = flat_package_unsigned_more_info[0];
3628 proc_with_initial_seg = flat_package_unsigned_more_info[1];
3629 proc_with_final_seg = flat_package_unsigned_more_info[2];
3630 initial_segment = flat_package_unsigned_more_info[3];
3631 final_segment = flat_package_unsigned_more_info[4];
3634 MPI_Bcast(&root_accumulated_arclength, 1, MPI_DOUBLE,
3635 root_processor, comm_pt->mpi_comm());
3644 Boundary_initial_coordinate[b].clear();
3645 Boundary_final_coordinate[b].clear();
3647 Boundary_initial_zeta_coordinate[b].clear();
3648 Boundary_final_zeta_coordinate[b].clear();
3651 Boundary_segment_inverted[b].clear();
3652 Boundary_segment_initial_coordinate[b].clear();
3653 Boundary_segment_final_coordinate[b].clear();
3655 Boundary_segment_initial_zeta[b].clear();
3656 Boundary_segment_final_zeta[b].clear();
3658 Boundary_segment_initial_arclength[b].clear();
3659 Boundary_segment_final_arclength[b].clear();
3663 for (
unsigned is = 0; is < nsegments; is++)
3676 segment_sorted_nonhalo_ele_pt[is].front();
3681 if (first_seg_ele_pt->
is_halo())
3683 std::ostringstream error_message;
3685 <<
"The first face element in the (" << is <<
")-th segment is halo\n";
3687 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3688 OOMPH_EXCEPTION_LOCATION);
3693 const unsigned nnod = first_seg_ele_pt->
nnode();
3696 Node *first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
3697 if (is_inverted[first_seg_ele_pt])
3699 first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);
3704 segment_sorted_nonhalo_ele_pt[is].back();
3709 if (last_seg_ele_pt->
is_halo())
3711 std::ostringstream error_message;
3713 <<
"The last face element in the (" << is <<
")-th segment is halo\n";
3715 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3716 OOMPH_EXCEPTION_LOCATION);
3721 Node *last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
3722 if (is_inverted[last_seg_ele_pt])
3724 last_seg_node_pt = last_seg_ele_pt->node_pt(0);
3728 for (
unsigned i = 0;
i < 2;
i++)
3730 first_seg_coord[
i] = first_seg_node_pt->
x(
i);
3731 last_seg_coord[
i] = last_seg_node_pt->
x(
i);
3736 Boundary_segment_inverted[b].push_back(segment_inverted[is]);
3740 if (!segment_inverted[is])
3744 Boundary_segment_initial_coordinate[b].push_back(first_seg_coord);
3745 Boundary_segment_final_coordinate[b].push_back(last_seg_coord);
3752 Boundary_segment_initial_coordinate[b].push_back(last_seg_coord);
3753 Boundary_segment_final_coordinate[b].push_back(first_seg_coord);
3760 if (boundary_geom_object_pt(b)!=0)
3765 if (segment_inverted[is])
3767 Boundary_segment_initial_zeta[b].push_back(final_zeta_segment[is]);
3768 Boundary_segment_final_zeta[b].push_back(initial_zeta_segment[is]);
3772 Boundary_segment_initial_zeta[b].push_back(initial_zeta_segment[is]);
3773 Boundary_segment_final_zeta[b].push_back(final_zeta_segment[is]);
3780 Boundary_segment_initial_arclength[b].push_back(
3781 initial_segment_arclength[is]);
3783 Boundary_segment_final_arclength[b].push_back(
3784 initial_segment_arclength[is] + segment_arclength[is]);
3792 if (segment_all_nodes_pt.size() != nsegments)
3794 std::ostringstream error_message;
3796 <<
"The number of segments ("<<nsegments<<
") and the number of "
3797 <<
"set of nodes ("<<segment_all_nodes_pt.size()<<
") representing\n"
3798 <<
"the\nsegments is different!!!\n\n";
3800 "TriangleMesh::compute_boundary_segments_connectivity_and_initial_zeta_values()",
3801 OOMPH_EXCEPTION_LOCATION);
3825 const unsigned ndtotal_data = 3;
3826 Vector<double> flat_packed_double_data_initial_seg(ndtotal_data);
3830 if (my_rank == proc_with_initial_seg)
3835 Node *first_node_pt = 0;
3837 if (!segment_inverted[initial_segment])
3841 first_ele_pt = segment_sorted_ele_pt[initial_segment].front();
3844 const unsigned nnod = first_ele_pt->
nnode();
3847 first_node_pt = first_ele_pt->
node_pt(0);
3848 if (is_inverted[first_ele_pt])
3850 first_node_pt = first_ele_pt->node_pt(nnod-1);
3857 first_ele_pt = segment_sorted_ele_pt[initial_segment].back();
3860 const unsigned nnod = first_ele_pt->
nnode();
3863 first_node_pt = first_ele_pt->
node_pt(nnod-1);
3864 if (is_inverted[first_ele_pt])
3866 first_node_pt = first_ele_pt->node_pt(0);
3871 for (
unsigned i = 0;
i < 2;
i++)
3873 flat_packed_double_data_initial_seg[
i] = first_node_pt->
x(
i);
3882 if (this->boundary_geom_object_pt(b)!=0)
3890 if (tmp_zeta[0] >= 1.0
e-14)
3897 flat_packed_double_data_initial_seg[2] = tmp_zeta[0];
3903 MPI_Bcast(&flat_packed_double_data_initial_seg[0], ndtotal_data,
3904 MPI_DOUBLE, proc_with_initial_seg, comm_pt->mpi_comm());
3908 for (
unsigned i = 0;
i < 2;
i++)
3910 first_coordinate[
i] = flat_packed_double_data_initial_seg[
i];
3912 first_node_zeta_coordinate[0]=flat_packed_double_data_initial_seg[2];
3921 if (my_rank == proc_with_final_seg)
3927 Node *last_node_pt = 0;
3930 if (!segment_inverted[final_segment])
3934 last_ele_pt = segment_sorted_ele_pt[final_segment].back();
3937 const unsigned nnod = last_ele_pt->
nnode();
3940 last_node_pt = last_ele_pt->
node_pt(nnod-1);
3941 if (is_inverted[last_ele_pt])
3943 last_node_pt = last_ele_pt->node_pt(0);
3950 last_ele_pt = segment_sorted_ele_pt[final_segment].front();
3953 const unsigned nnod = last_ele_pt->
nnode();
3956 last_node_pt = last_ele_pt->
node_pt(0);
3957 if (is_inverted[last_ele_pt])
3959 last_node_pt = last_ele_pt->node_pt(nnod-1);
3964 for (
unsigned i = 0;
i < 2;
i++)
3966 flat_packed_double_data_final_seg[
i]=last_node_pt->
x(
i);
3975 if (this->boundary_geom_object_pt(b)!=0)
3984 if (std::fabs(tmp_zeta[0] - root_accumulated_arclength) >= 1.0
e-14)
3986 tmp_zeta[0] = root_accumulated_arclength;
3991 flat_packed_double_data_final_seg[2] = tmp_zeta[0];
3997 MPI_Bcast(&flat_packed_double_data_final_seg[0], ndtotal_data,
3998 MPI_DOUBLE, proc_with_final_seg, comm_pt->mpi_comm());
4002 for (
unsigned i = 0;
i < 2;
i++)
4004 last_coordinate[
i] = flat_packed_double_data_final_seg[
i];
4006 last_node_zeta_coordinate[0]=flat_packed_double_data_final_seg[2];
4010 Boundary_initial_coordinate[b] = first_coordinate;
4011 Boundary_final_coordinate[b] = last_coordinate;
4013 Boundary_initial_zeta_coordinate[b] = first_node_zeta_coordinate;
4014 Boundary_final_zeta_coordinate[b] = last_node_zeta_coordinate;
4018 if (is_internal_boundary)
4029 re_assign_initial_zeta_values_for_internal_boundary(
4030 b, segment_sorted_nonhalo_ele_pt, is_inverted);
4041 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
4045 for (
unsigned i = 0;
i < n_all_face_ele;
i++)
4047 delete all_face_ele_pt[
i];
4048 all_face_ele_pt[
i] = 0;
4061 template<
class ELEMENT>
4065 Vector<std::list<FiniteElement*> > &old_segment_sorted_ele_pt,
4066 std::map<FiniteElement*, bool> &old_is_inverted)
4081 unsigned n_repeated_ele = 0;
4083 const unsigned n_regions = this->nregion();
4092 for (
unsigned rr = 0 ; rr < n_regions; rr++)
4094 const unsigned region_id =
4095 static_cast<unsigned>(this->Region_attribute[rr]);
4098 const unsigned nel_in_region =
4099 this->nboundary_element_in_region(b, region_id);
4101 unsigned nel_repetead_in_region = 0;
4105 if (nel_in_region > 0)
4107 bool repeated =
false;
4110 for (
unsigned e = 0;
e < nel_in_region;
e++)
4115 this->boundary_element_in_region_pt(b, region_id,
e);
4126 this->face_index_at_boundary_in_region(b,region_id,
e);
4134 const unsigned n_nodes = tmp_ele_pt->
nnode();
4136 std::pair<Node*, Node*> tmp_pair =
4137 std::make_pair(tmp_ele_pt->
node_pt(0),
4138 tmp_ele_pt->
node_pt(n_nodes - 1));
4140 std::pair<Node*, Node*> tmp_pair_inverse =
4141 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
4145 const unsigned repeated_nodes_size = done_nodes_pt.size();
4146 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4148 if (tmp_pair == done_nodes_pt[l] ||
4149 tmp_pair_inverse == done_nodes_pt[l])
4151 nel_repetead_in_region++;
4161 done_nodes_pt.push_back(tmp_pair);
4163 face_el_pt.push_back(tmp_ele_pt);
4177 nele += nel_in_region;
4179 n_repeated_ele += nel_repetead_in_region;
4188 nele = this->nboundary_element(b);
4194 bool repeated =
false;
4197 for (
unsigned e = 0;
e < nele;
e++)
4211 int face_index = this->face_index_at_boundary(b,
e);
4219 const unsigned n_nodes = tmp_ele_pt->
nnode();
4221 std::pair<Node*, Node*> tmp_pair =
4222 std::make_pair(tmp_ele_pt->
node_pt(0),
4223 tmp_ele_pt->
node_pt(n_nodes - 1));
4225 std::pair<Node*, Node*> tmp_pair_inverse =
4226 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
4230 const unsigned repeated_nodes_size = done_nodes_pt.size();
4231 for (
unsigned l = 0; l < repeated_nodes_size; l++)
4233 if (tmp_pair == done_nodes_pt[l] ||
4234 tmp_pair_inverse == done_nodes_pt[l])
4248 done_nodes_pt.push_back(tmp_pair);
4250 face_el_pt.push_back(tmp_ele_pt);
4268 nele-= n_repeated_ele;
4271 if (nele!=face_el_pt.size())
4273 std::ostringstream error_message;
4275 <<
"The independet counting of face elements ("<<nele<<
") for "
4276 <<
"boundary ("<<b<<
") is different\n"
4277 <<
"from the real number of face elements in the container ("
4278 << face_el_pt.size() <<
")\n";
4281 OOMPH_CURRENT_FUNCTION,
4282 OOMPH_EXCEPTION_LOCATION);
4291 const unsigned nnon_halo_face_elements = face_el_pt.size();
4298 unsigned nsorted_face_elements = 0;
4301 std::map<FiniteElement*, bool> done_el;
4304 std::map<FiniteElement*, bool> is_inverted;
4307 while(nsorted_face_elements < nnon_halo_face_elements)
4311 std::list<FiniteElement*> sorted_el_pt;
4315 bool found_initial_face_element =
false;
4321 for (iface = 0; iface < nele; iface++)
4323 ele_face_pt = face_el_pt[iface];
4325 if (!done_el[ele_face_pt])
4329 found_initial_face_element =
true;
4332 nsorted_face_elements++;
4337 sorted_el_pt.push_back(ele_face_pt);
4339 done_el[ele_face_pt] =
true;
4345 if (!found_initial_face_element)
4347 std::ostringstream error_message;
4349 <<
"Could not find an initial face element for the current segment\n";
4351 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4352 OOMPH_EXCEPTION_LOCATION);
4357 const unsigned nnod = ele_face_pt->
nnode();
4362 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
4366 bool face_element_added =
false;
4375 for (
unsigned iiface = iface; iiface < nele; iiface++)
4378 face_element_added =
false;
4381 ele_face_pt = face_el_pt[iiface];
4385 if (!(done_el[ele_face_pt]))
4388 Node* local_left_node_pt = ele_face_pt->node_pt(0);
4389 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
4392 if (left_node_pt == local_right_node_pt)
4394 left_node_pt = local_left_node_pt;
4395 sorted_el_pt.push_front(ele_face_pt);
4396 is_inverted[ele_face_pt] =
false;
4397 face_element_added =
true;
4400 else if (left_node_pt == local_left_node_pt)
4402 left_node_pt = local_right_node_pt;
4403 sorted_el_pt.push_front(ele_face_pt);
4404 is_inverted[ele_face_pt] =
true;
4405 face_element_added =
true;
4408 else if (right_node_pt == local_left_node_pt)
4410 right_node_pt = local_right_node_pt;
4411 sorted_el_pt.push_back(ele_face_pt);
4412 is_inverted[ele_face_pt] =
false;
4413 face_element_added =
true;
4416 else if (right_node_pt == local_right_node_pt)
4418 right_node_pt = local_left_node_pt;
4419 sorted_el_pt.push_back(ele_face_pt);
4420 is_inverted[ele_face_pt] =
true;
4421 face_element_added =
true;
4424 if (face_element_added)
4426 done_el[ele_face_pt] =
true;
4427 nsorted_face_elements++;
4435 }
while(face_element_added &&
4436 (nsorted_face_elements < nnon_halo_face_elements));
4439 segment_sorted_ele_pt.push_back(sorted_el_pt);
4450 const unsigned nsegments = segment_sorted_ele_pt.size();
4453 if (nnon_halo_face_elements > 0 && nsegments == 0)
4455 std::ostringstream error_message;
4457 <<
"The number of segments is zero, but the number of nonhalo\n"
4458 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
4460 OOMPH_CURRENT_FUNCTION,
4461 OOMPH_EXCEPTION_LOCATION);
4493 for (
unsigned is = 0; is < nsegments; is++)
4496 if (segment_sorted_ele_pt[is].size() == 0)
4498 std::ostringstream error_message;
4500 <<
"The (" << is <<
")-th segment has no elements\n";
4502 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
4503 OOMPH_EXCEPTION_LOCATION);
4508 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
4511 const unsigned nnod = first_ele_pt->
nnode();
4515 if (is_inverted[first_ele_pt])
4517 first_node_pt = first_ele_pt->node_pt(nnod-1);
4521 double x_left = first_node_pt->
x(0);
4522 double y_left = first_node_pt->
x(1);
4531 if (this->boundary_geom_object_pt(b)!=0)
4534 initial_zeta_segment[is] = zeta[0];
4537 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
4540 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
4541 if (is_inverted[last_ele_pt])
4543 last_node_pt = last_ele_pt->node_pt(0);
4547 final_zeta_segment[is] = zeta[0];
4552 std::set<Node*> local_nodes_pt;
4553 local_nodes_pt.insert(first_node_pt);
4557 sorted_node_arclength.push_back(0.0);
4562 sorted_nodes_pt.push_back(first_node_pt);
4565 for (std::list<FiniteElement*>::iterator it =
4566 segment_sorted_ele_pt[is].begin();
4567 it != segment_sorted_ele_pt[is].end(); it++)
4575 if (is_inverted[el_pt])
4582 for (
unsigned j = 1; j < nnod; j++)
4584 Node* nod_pt = el_pt->node_pt(k_nod);
4588 double x_right = nod_pt->
x(0);
4589 double y_right = nod_pt->
x(1);
4593 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
4594 * (y_right - y_left));
4599 if (this->boundary_geom_object_pt(b)==0)
4611 local_nodes_pt.insert(nod_pt);
4614 sorted_node_arclength.push_back(zeta[0]);
4617 sorted_nodes_pt.push_back(nod_pt);
4626 segment_arclength[is] = zeta[0];
4631 nvertices_per_segment[is] = local_nodes_pt.size();
4634 segment_all_nodes_pt[is] = local_nodes_pt;
4637 sorted_segment_node_arclength[is] = sorted_node_arclength;
4640 sorted_segment_all_nodes_pt[is] = sorted_nodes_pt;
4655 const unsigned old_nsegments = old_segment_sorted_ele_pt.size();
4662 old_boundary_segment_initial_coordinate(old_nsegments);
4664 old_boundary_segment_final_coordinate(old_nsegments);
4669 Vector<double> old_boundary_segment_initial_arclength(old_nsegments);
4670 Vector<double> old_boundary_segment_final_arclength(old_nsegments);
4673 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4675 old_boundary_segment_inverted[old_is] =
4676 boundary_segment_inverted(b)[old_is];
4678 old_boundary_segment_initial_coordinate[old_is].resize(2);
4679 old_boundary_segment_final_coordinate[old_is].resize(2);
4680 for (
unsigned i = 0;
i < 2;
i++)
4682 old_boundary_segment_initial_coordinate[old_is][
i] =
4683 boundary_segment_initial_coordinate(b)[old_is][
i];
4685 old_boundary_segment_final_coordinate[old_is][
i] =
4686 boundary_segment_final_coordinate(b)[old_is][
i];
4690 if (this->boundary_geom_object_pt(b)!=0)
4692 old_boundary_segment_initial_zeta[old_is] =
4693 boundary_segment_initial_zeta(b)[old_is];
4695 old_boundary_segment_final_zeta[old_is] =
4696 boundary_segment_final_zeta(b)[old_is];
4701 old_boundary_segment_initial_arclength[old_is] =
4702 boundary_segment_initial_arclength(b)[old_is];
4704 old_boundary_segment_final_arclength[old_is] =
4705 boundary_segment_final_arclength(b)[old_is];
4713 Boundary_segment_inverted[b].clear();
4714 Boundary_segment_initial_coordinate[b].clear();
4715 Boundary_segment_final_coordinate[b].clear();
4717 Boundary_segment_initial_zeta[b].clear();
4718 Boundary_segment_final_zeta[b].clear();
4720 Boundary_segment_initial_arclength[b].clear();
4721 Boundary_segment_final_arclength[b].clear();
4724 Boundary_segment_inverted[b].resize(nsegments);
4725 Boundary_segment_initial_coordinate[b].resize(nsegments);
4726 Boundary_segment_final_coordinate[b].resize(nsegments);
4729 if (this->boundary_geom_object_pt(b)!=0)
4731 Boundary_segment_initial_zeta[b].resize(nsegments);
4732 Boundary_segment_final_zeta[b].resize(nsegments);
4736 Boundary_segment_initial_arclength[b].resize(nsegments);
4737 Boundary_segment_final_arclength[b].resize(nsegments);
4741 std::map<unsigned, bool> done_segment;
4744 unsigned re_assigned_segments = 0;
4747 for (
unsigned old_is = 0; old_is < old_nsegments; old_is++)
4750 const double old_initial_arclength =
4751 old_boundary_segment_initial_arclength[old_is];
4752 const double old_final_arclength =
4753 old_boundary_segment_final_arclength[old_is];
4755 const unsigned old_inverted_segment =
4756 old_boundary_segment_inverted[old_is];
4760 bool old_increasing_order =
false;
4761 if (old_initial_arclength < old_final_arclength)
4762 {old_increasing_order =
true;}
4767 old_segment_sorted_ele_pt[old_is].front();
4770 const unsigned nnod = first_old_seg_ele_pt->
nnode();
4773 Node *first_old_seg_node_pt = first_old_seg_ele_pt->
node_pt(0);
4774 if (old_is_inverted[first_old_seg_ele_pt])
4776 first_old_seg_node_pt = first_old_seg_ele_pt->node_pt(nnod-1);
4781 old_segment_sorted_ele_pt[old_is].back();
4784 Node *last_old_seg_node_pt = last_old_seg_ele_pt->
node_pt(nnod-1);
4785 if (old_is_inverted[last_old_seg_ele_pt])
4787 last_old_seg_node_pt = last_old_seg_ele_pt->node_pt(0);
4791 if (old_inverted_segment)
4793 Node* temp_node_pt = first_old_seg_node_pt;
4794 first_old_seg_node_pt = last_old_seg_node_pt;
4795 last_old_seg_node_pt = temp_node_pt;
4801 for (
unsigned is = 0; is < nsegments; is++)
4803 if (!done_segment[is])
4807 bool found_first_old_seg_node =
false;
4808 bool found_last_old_seg_node =
false;
4809 bool same_order =
false;
4812 FiniteElement* first_seg_ele_pt = segment_sorted_ele_pt[is].front();
4813 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
4814 if (is_inverted[first_seg_ele_pt])
4815 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
4818 const double segment_first_node_zeta =
4819 sorted_segment_node_arclength[is][0];
4823 for (
unsigned i = 0;
i < 2;
i++)
4824 {first_node_coord[
i] = first_seg_node_pt->
x(
i);}
4827 FiniteElement* last_seg_ele_pt = segment_sorted_ele_pt[is].back();
4828 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
4829 if (is_inverted[last_seg_ele_pt])
4830 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
4833 const double segment_final_node_zeta = segment_arclength[is];
4837 for (
unsigned i = 0;
i < 2;
i++)
4838 {last_node_coord[
i] = last_seg_node_pt->
x(
i);}
4841 Vector<Node*> segment_node_pt = sorted_segment_all_nodes_pt[is];
4843 const unsigned nsegment_node = segment_node_pt.size();
4844 for (
unsigned in = 0; in < nsegment_node; in++)
4846 Node* current_node_pt = segment_node_pt[in];
4847 if (!found_first_old_seg_node &&
4848 first_old_seg_node_pt == current_node_pt)
4852 const double current_node_zeta =
4853 sorted_segment_node_arclength[is][in];
4857 if (!found_last_old_seg_node)
4860 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
4863 if (this->boundary_geom_object_pt(b)!=0)
4870 Boundary_segment_initial_zeta[b][is] =
4871 initial_zeta_segment[is];
4877 const double distance =
4878 std::fabs(current_node_zeta - segment_first_node_zeta);
4880 double new_initial_arclength = old_initial_arclength;
4883 if (old_increasing_order)
4886 new_initial_arclength-= distance;
4891 new_initial_arclength+= distance;
4895 Boundary_segment_initial_arclength[b][is] =
4896 new_initial_arclength;
4903 Boundary_segment_initial_coordinate[b][is] = last_node_coord;
4906 if (this->boundary_geom_object_pt(b)!=0)
4914 Boundary_segment_initial_zeta[b][is] =
4915 final_zeta_segment[is];
4921 const double distance =
4922 std::fabs(current_node_zeta - segment_final_node_zeta);
4924 double new_initial_arclength = old_initial_arclength;
4927 if (old_increasing_order)
4930 new_initial_arclength-= distance;
4935 new_initial_arclength+= distance;
4939 Boundary_segment_initial_arclength[b][is] =
4940 new_initial_arclength;
4946 found_first_old_seg_node =
true;
4954 if (found_first_old_seg_node && !found_last_old_seg_node)
4955 {same_order =
true;}
4957 if (!found_last_old_seg_node &&
4958 last_old_seg_node_pt == current_node_pt)
4962 const double current_node_zeta =
4963 sorted_segment_node_arclength[is][in];
4967 if (found_first_old_seg_node)
4970 Boundary_segment_final_coordinate[b][is] = last_node_coord;
4973 if (this->boundary_geom_object_pt(b)!=0)
4980 Boundary_segment_final_zeta[b][is] =
4981 final_zeta_segment[is];
4987 const double distance =
4988 std::fabs(current_node_zeta - segment_final_node_zeta);
4990 double new_final_arclength = old_final_arclength;
4993 if (old_increasing_order)
4996 new_final_arclength+= distance;
5001 new_final_arclength-= distance;
5005 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5012 Boundary_segment_final_coordinate[b][is] = first_node_coord;
5015 if (this->boundary_geom_object_pt(b)!=0)
5023 Boundary_segment_final_zeta[b][is] =
5024 initial_zeta_segment[is];
5030 const double distance =
5031 std::fabs(current_node_zeta - segment_first_node_zeta);
5033 double new_final_arclength = old_final_arclength;
5036 if (old_increasing_order)
5039 new_final_arclength+= distance;
5044 new_final_arclength-= distance;
5048 Boundary_segment_final_arclength[b][is] = new_final_arclength;
5054 found_last_old_seg_node =
true;
5061 if (!found_first_old_seg_node && found_last_old_seg_node)
5062 {same_order =
false;}
5064 if (found_first_old_seg_node && found_last_old_seg_node)
5069 {Boundary_segment_inverted[b][is] = old_inverted_segment;}
5071 {Boundary_segment_inverted[b][is] = !old_inverted_segment;}
5074 done_segment[is] =
true;
5077 re_assigned_segments++;
5086 if ((found_first_old_seg_node && !found_last_old_seg_node) ||
5087 (!found_first_old_seg_node && found_last_old_seg_node))
5089 std::stringstream error_message;
5091 <<
"Working with boundary ("<< b <<
").\nOnly the first node or "
5092 <<
"the last node of the old segment (" << old_is <<
") was\n"
5093 <<
"found. Both, first and last node should have been found in "
5094 <<
"the same segment!!!.\n"
5095 <<
"Found first seg node:" << found_first_old_seg_node <<
"\n"
5096 <<
"Found last seg node:" << found_last_old_seg_node <<
"\n\n";
5098 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5099 OOMPH_EXCEPTION_LOCATION);
5112 for (
unsigned is = 0; is < nsegments; is++)
5115 if (!done_segment[is])
5119 segment_sorted_ele_pt[is].front();
5121 const unsigned nnod = first_seg_ele_pt->
nnode();
5123 Node* first_seg_node_pt = first_seg_ele_pt->
node_pt(0);
5124 if (is_inverted[first_seg_ele_pt])
5125 {first_seg_node_pt = first_seg_ele_pt->node_pt(nnod-1);}
5128 const double segment_first_node_zeta =
5129 sorted_segment_node_arclength[is][0];
5133 for (
unsigned i = 0;
i < 2;
i++)
5134 {first_node_coord[
i] = first_seg_node_pt->
x(
i);}
5138 segment_sorted_ele_pt[is].back();
5139 Node* last_seg_node_pt = last_seg_ele_pt->
node_pt(nnod-1);
5140 if (is_inverted[last_seg_ele_pt])
5141 {last_seg_node_pt = last_seg_ele_pt->node_pt(0);}
5144 const double segment_final_node_zeta = segment_arclength[is];
5148 for (
unsigned i = 0;
i < 2;
i++)
5149 {last_node_coord[
i] = last_seg_node_pt->
x(
i);}
5152 Boundary_segment_initial_coordinate[b][is] = first_node_coord;
5155 if (this->boundary_geom_object_pt(b)!=0)
5162 Boundary_segment_initial_zeta[b][is] =
5163 initial_zeta_segment[is];
5169 Boundary_segment_initial_arclength[b][is] =
5170 segment_first_node_zeta;
5175 Boundary_segment_final_coordinate[b][is] = last_node_coord;
5178 if (this->boundary_geom_object_pt(b)!=0)
5185 Boundary_segment_final_zeta[b][is] =
5186 final_zeta_segment[is];
5192 Boundary_segment_final_arclength[b][is] =
5193 segment_final_node_zeta;
5197 Boundary_segment_inverted[b][is] = 0;
5200 done_segment[is] =
true;
5203 re_assigned_segments++;
5211 if (re_assigned_segments != nsegments)
5213 std::stringstream error_message;
5215 <<
"Working with boundary ("<< b <<
").\nThe number of re-assigned "
5216 <<
"segments (" << re_assigned_segments
5217 <<
") is different from the number\nof segments ("<< nsegments
5220 "TriangleMesh::re_assign_initial_zeta_values_for_internal_boundary()",
5221 OOMPH_EXCEPTION_LOCATION);
5226 for (
unsigned i = 0;
i < nele;
i++)
5228 delete face_el_pt[
i];
5243 template <
class ELEMENT>
5247 bool &is_internal_boundary,
5248 std::map<FiniteElement*,FiniteElement*>
5249 &face_to_bulk_element_pt)
5254 const unsigned my_rank = comm_pt->my_rank();
5264 const unsigned nregions = this->nregion();
5270 for (
unsigned ir = 0 ; ir < nregions; ir++)
5272 const unsigned region_id =
5273 static_cast<unsigned>(this->Region_attribute[ir]);
5276 const unsigned nele_in_region =
5277 this->nboundary_element_in_region(b, region_id);
5281 if (nele_in_region > 0)
5284 for (
unsigned e = 0;
e < nele_in_region;
e++)
5289 this->boundary_element_in_region_pt(b, region_id,
e);
5294 this->face_index_at_boundary_in_region(b,region_id,
e);
5301 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5306 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5320 const unsigned nbound_ele = this->nboundary_element(b);
5326 for (
unsigned e = 0;
e < nbound_ele;
e++)
5334 int face_index = this->face_index_at_boundary(b,
e);
5341 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5346 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5355 std::map<FiniteElement*,bool> done_face;
5359 is_internal_boundary =
false;
5367 const unsigned n_tmp_face_ele = tmp_face_ele_pt.size();
5368 for (
unsigned ie = 0; ie < n_tmp_face_ele; ie++)
5372 if (!done_face[main_face_ele_pt])
5375 done_face[main_face_ele_pt] =
true;
5377 const unsigned nnodes = main_face_ele_pt->nnode();
5379 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5380 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5384 for (
unsigned iie = ie + 1; iie < n_tmp_face_ele; iie++)
5387 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5388 if (!done_face[dependant_face_ele_pt])
5392 Node* dependant_first_node_pt =
5393 dependant_face_ele_pt->node_pt(0);
5394 Node* dependant_last_node_pt =
5395 dependant_face_ele_pt->node_pt(nnodes-1);
5398 if (((dependant_first_node_pt == main_first_node_pt) &&
5399 (dependant_last_node_pt == main_last_node_pt)) ||
5400 ((dependant_first_node_pt == main_last_node_pt) &&
5401 (dependant_last_node_pt == main_first_node_pt)))
5405 is_internal_boundary =
true;
5407 done_face[dependant_face_ele_pt] =
true;
5419 face_to_bulk_element_pt[main_face_ele_pt];
5421 face_to_bulk_element_pt[dependant_face_ele_pt];
5425 int processor_in_charge_main_bulk_ele =
5427 int processor_in_charge_dependant_bulk_ele =
5433 if (processor_in_charge_main_bulk_ele < 0)
5435 processor_in_charge_main_bulk_ele=
5436 static_cast<int>(my_rank);
5438 if (processor_in_charge_dependant_bulk_ele < 0)
5440 processor_in_charge_dependant_bulk_ele=
5441 static_cast<int>(my_rank);
5446 bool add_main_face_element =
true;
5447 if (processor_in_charge_dependant_bulk_ele >
5448 processor_in_charge_main_bulk_ele)
5451 add_main_face_element =
false;
5453 else if (processor_in_charge_main_bulk_ele ==
5454 processor_in_charge_dependant_bulk_ele)
5464 const unsigned n_bulk_nodes =
5465 main_bulk_ele_pt->
nnode();
5466 for (
unsigned inode = 0; inode < n_bulk_nodes;
5469 for (
unsigned idim = 0; idim < 2; idim++)
5471 main_ele_coordinates[idim]+=
5472 main_bulk_ele_pt->
node_pt(inode)->
5474 dependant_ele_coordinates[idim]+=
5475 dependant_bulk_ele_pt->
node_pt(inode)->
5482 for (
unsigned idim = 0; idim < 2; idim++)
5484 main_ele_coordinates[idim]/=
5485 (double)n_bulk_nodes;
5486 dependant_ele_coordinates[idim]/=
5487 (double)n_bulk_nodes;
5493 if (dependant_ele_coordinates[1] <
5494 main_ele_coordinates[1])
5495 {add_main_face_element =
false;}
5496 else if(dependant_ele_coordinates[1]==
5497 main_ele_coordinates[1])
5500 if(dependant_ele_coordinates[0] <
5501 main_ele_coordinates[0])
5502 {add_main_face_element =
false;}
5507 if (add_main_face_element)
5512 face_ele_pt.push_back(main_face_ele_pt);
5515 free_memory_face_ele_pt.
5516 push_back(dependant_face_ele_pt);
5523 face_ele_pt.push_back(dependant_face_ele_pt);
5526 free_memory_face_ele_pt.
5527 push_back(main_face_ele_pt);
5546 const unsigned n_free_face_ele = free_memory_face_ele_pt.size();
5547 if (n_free_face_ele == 0)
5555 face_ele_pt.resize(n_tmp_face_ele);
5557 for (
unsigned i = 0;
i < n_tmp_face_ele;
i++)
5559 face_ele_pt[
i] = tmp_face_ele_pt[
i];
5567 for (
unsigned i = 0;
i < n_free_face_ele;
i++)
5569 delete free_memory_face_ele_pt[
i];
5570 free_memory_face_ele_pt[
i] = 0;
5582 template <
class ELEMENT>
5593 const unsigned nproc = comm_pt->nproc();
5594 const unsigned my_rank = comm_pt->my_rank();
5600 const unsigned nregions = this->nregion();
5604 std::map<FiniteElement*,FiniteElement*> face_to_bulk_element_pt;
5610 for (
unsigned ir = 0 ; ir < nregions; ir++)
5612 const unsigned region_id =
5613 static_cast<unsigned>(this->Region_attribute[ir]);
5616 const unsigned nele_in_region =
5617 this->nboundary_element_in_region(b, region_id);
5621 if (nele_in_region > 0)
5624 for (
unsigned e = 0;
e < nele_in_region;
e++)
5628 this->boundary_element_in_region_pt(b, region_id,
e);
5631 int face_index=this->face_index_at_boundary_in_region(b,region_id,
e);
5640 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5642 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5656 const unsigned nbound_ele = this->nboundary_element(b);
5662 for (
unsigned e = 0;
e < nbound_ele;
e++)
5668 int face_index = this->face_index_at_boundary(b,
e);
5676 tmp_face_ele_pt.push_back(tmp_face_el_pt);
5678 face_to_bulk_element_pt[tmp_face_el_pt] = bulk_ele_pt;
5692 std::map<FiniteElement*,bool> done_face;
5695 bool is_internal_boundary =
false;
5699 bool is_internal_boundary_paranoid =
false;
5703 unsigned nfound_face_elements = 0;
5707 const unsigned nbound_ele = tmp_face_ele_pt.size();
5708 for (
unsigned ie = 0; ie < nbound_ele; ie++)
5712 if (!done_face[main_face_ele_pt])
5715 done_face[main_face_ele_pt] =
true;
5717 const unsigned nnodes = main_face_ele_pt->nnode();
5719 Node* main_first_node_pt = main_face_ele_pt->node_pt(0);
5720 Node* main_last_node_pt = main_face_ele_pt->node_pt(nnodes-1);
5722 for (
unsigned iie = ie + 1; iie < nbound_ele; iie++)
5725 FiniteElement* dependant_face_ele_pt = tmp_face_ele_pt[iie];
5726 if (!done_face[dependant_face_ele_pt])
5729 Node* dependant_first_node_pt =
5730 dependant_face_ele_pt->node_pt(0);
5731 Node* dependant_last_node_pt =
5732 dependant_face_ele_pt->node_pt(nnodes-1);
5735 if (((dependant_first_node_pt == main_first_node_pt) &&
5736 (dependant_last_node_pt == main_last_node_pt)) ||
5737 ((dependant_first_node_pt == main_last_node_pt) &&
5738 (dependant_last_node_pt == main_first_node_pt)))
5742 nfound_face_elements+=2;
5746 is_internal_boundary =
true;
5748 done_face[dependant_face_ele_pt] =
true;
5758 face_to_bulk_element_pt[main_face_ele_pt];
5760 face_to_bulk_element_pt[dependant_face_ele_pt];
5763 int processor_in_charge_main_bulk_ele =
5765 int processor_in_charge_dependant_bulk_ele =
5771 if (processor_in_charge_main_bulk_ele < 0)
5773 processor_in_charge_main_bulk_ele=
static_cast<int>(my_rank);
5775 if (processor_in_charge_dependant_bulk_ele < 0)
5777 processor_in_charge_dependant_bulk_ele=
static_cast<int>(my_rank);
5781 bool add_main_face_element =
true;
5782 if (processor_in_charge_dependant_bulk_ele >
5783 processor_in_charge_main_bulk_ele)
5786 add_main_face_element =
false;
5788 else if (processor_in_charge_main_bulk_ele ==
5789 processor_in_charge_dependant_bulk_ele)
5797 const unsigned n_bulk_nodes = main_bulk_ele_pt->
nnode();
5798 for (
unsigned inode = 0; inode < n_bulk_nodes; inode++)
5800 for (
unsigned idim = 0; idim < 2; idim++)
5802 main_ele_coordinates[idim]+=
5803 main_bulk_ele_pt->
node_pt(inode)->
x(idim);
5804 dependant_ele_coordinates[idim]+=
5805 dependant_bulk_ele_pt->
node_pt(inode)->
x(idim);
5810 for (
unsigned idim = 0; idim < 2; idim++)
5812 main_ele_coordinates[idim]/=(double)n_bulk_nodes;
5813 dependant_ele_coordinates[idim]/=(double)n_bulk_nodes;
5819 if (dependant_ele_coordinates[1] < main_ele_coordinates[1])
5820 {add_main_face_element =
false;}
5821 else if(dependant_ele_coordinates[1]==main_ele_coordinates[1])
5824 if(dependant_ele_coordinates[0] < main_ele_coordinates[0])
5825 {add_main_face_element =
false;}
5830 if (add_main_face_element)
5834 face_ele_pt.push_back(main_face_ele_pt);
5840 face_ele_pt.push_back(dependant_face_ele_pt);
5853 const unsigned nface_ele = face_ele_pt.size();
5859 if (nbound_ele > 0 && nfound_face_elements == nbound_ele)
5860 {is_internal_boundary_paranoid =
true;}
5862 if (nbound_ele > 0 && is_internal_boundary_paranoid &&
5863 nbound_ele!=nface_ele*2)
5865 std::ostringstream error_message;
5867 <<
"The info. to perform the synchronisation of the boundary "
5868 <<
"coordinates was not completely established\n"
5869 <<
"In this case it was the number of non repeated boundary elements\n"
5870 <<
"Number of boundary elements: (" << nbound_ele <<
")\n"
5871 <<
"Number of nonrepeated boundary elements: (" << nface_ele <<
")\n";
5873 "TriangleMesh::synchronize_boundary_coordinates()",
5874 OOMPH_EXCEPTION_LOCATION);
5884 std::vector<bool> is_halo_face_element(nface_ele,
false);
5887 unsigned nnon_halo_face_elements = 0;
5889 for (
unsigned ie = 0; ie < nface_ele; ie++)
5893 FiniteElement* tmp_bulk_ele_pt = face_to_bulk_element_pt[face_el_pt];
5895 if (!tmp_bulk_ele_pt->
is_halo())
5897 is_halo_face_element[ie] =
false;
5898 nnon_halo_face_elements++;
5903 is_halo_face_element[ie] =
true;
5916 std::map<Node*,bool> done_node;
5936 std::map<Node*,bool> done_haloed_face_node;
5939 for (
unsigned iface = 0; iface < nface_ele; iface++)
5942 if (!is_halo_face_element[iface])
5947 const unsigned nnodes = ele_face_pt->
nnode();
5949 for (
unsigned in = 0; in < nnodes; in++)
5953 if (!done_node[face_node_pt])
5956 done_node[face_node_pt] =
true;
5958 if (face_node_pt->is_halo())
5963 if (int_nonhalo_ID < 0)
5965 std::ostringstream error_message;
5967 <<
"The node was marked to be halo but the processor in "
5968 <<
"charge was found to be -1\n\n";
5970 "TriangleMesh::synchronize_boundary_coordinates()",
5971 OOMPH_EXCEPTION_LOCATION);
5974 const unsigned ip =
static_cast<unsigned>(int_nonhalo_ID);
5978 face_halo_node_pt[ip].push_back(face_node_pt);
5982 bool found_halo_node =
false;
5984 const unsigned nhalo_iproc = this->nhalo_node(ip);
5985 for (
unsigned ihn = 0; ihn < nhalo_iproc; ihn++)
5987 Node* compare_face_node_pt = this->halo_node_pt(ip, ihn);
5988 if (compare_face_node_pt == face_node_pt)
5992 face_halo_node_id[ip].push_back(ihn);
5995 found_halo_node =
true;
6002 if (!found_halo_node)
6004 std::ostringstream error_message;
6006 <<
"The halo id of the current node: ("
6007 << face_node_pt->x(0) <<
", " << face_node_pt->x(1)
6008 <<
") with processor (" << ip <<
") was not found!!!\n\n";
6010 "TriangleMesh::synchronize_boundary_coordinates()",
6011 OOMPH_EXCEPTION_LOCATION);
6021 for (
unsigned ip = 0; ip < nproc; ip++)
6033 const unsigned nhaloed_iproc = this->nhaloed_node(ip);
6034 for (
unsigned ihdn = 0; ihdn < nhaloed_iproc; ihdn++)
6036 Node* compare_face_node_pt=this->haloed_node_pt(ip, ihdn);
6037 if (face_node_pt == compare_face_node_pt)
6041 face_haloed_node_pt[ip].push_back(face_node_pt);
6044 face_haloed_node_id[ip].push_back(ihdn);
6048 done_haloed_face_node[face_node_pt] =
true;
6074 for (
unsigned ip = 0; ip < nproc; ip++)
6079 const unsigned nhalo_face_nodes = face_halo_node_pt[ip].size();
6081 if (nhalo_face_nodes!=face_halo_node_id[ip].size())
6083 std::ostringstream error_message;
6085 <<
"The number of found halo face nodes (" << nhalo_face_nodes
6086 <<
") is different from the number of\nfound halo face ids ("
6087 << face_halo_node_id[ip].size() <<
")!!!\n\n";
6089 "TriangleMesh::synchronize_boundary_coordinates()",
6090 OOMPH_EXCEPTION_LOCATION);
6100 for (
unsigned ihfn = 0; ihfn < nhalo_face_nodes; ihfn++)
6103 Node *halo_face_node_pt = face_halo_node_pt[ip][ihfn];
6105 const unsigned halo_id = face_halo_node_id[ip][ihfn];
6110 flat_unsigned_send_packed_data.push_back(halo_id);
6111 flat_double_send_packed_data.push_back(zeta[0]);
6116 MPI_Request request;
6119 int send_proc =
static_cast<int>(ip);
6121 int receive_proc =
static_cast<int>(ip);
6129 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6130 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6131 send_proc,1,comm_pt->mpi_comm(),&request);
6133 unsigned nflat_unsigned_receive = 0;
6134 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6135 receive_proc,1,comm_pt->mpi_comm(),&status);
6137 MPI_Wait(&request,MPI_STATUS_IGNORE);
6139 if (nflat_unsigned_send!=0)
6141 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6142 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6145 if (nflat_unsigned_receive!=0)
6147 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6148 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6149 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6152 if (nflat_unsigned_send!=0)
6154 MPI_Wait(&request,MPI_STATUS_IGNORE);
6159 unsigned nflat_double_send = flat_double_send_packed_data.size();
6160 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6161 send_proc,3,comm_pt->mpi_comm(),&request);
6163 unsigned nflat_double_receive = 0;
6164 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6165 receive_proc,3,comm_pt->mpi_comm(),&status);
6167 MPI_Wait(&request,MPI_STATUS_IGNORE);
6169 if (nflat_double_send!=0)
6171 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6172 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6175 if (nflat_double_receive!=0)
6177 flat_double_receive_packed_data.resize(nflat_double_receive);
6178 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6179 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6182 if (nflat_double_send!=0)
6184 MPI_Wait(&request,MPI_STATUS_IGNORE);
6189 if (nflat_unsigned_receive!=nflat_double_receive)
6191 std::ostringstream error_message;
6193 <<
"The number of unsigned received data ("
6194 << nflat_unsigned_receive <<
") is different from the "
6195 <<
"number\nof double received data ("
6196 << nflat_double_receive <<
")!!!\n\n";
6198 "TriangleMesh::synchronize_boundary_coordinates()",
6199 OOMPH_EXCEPTION_LOCATION);
6206 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6210 const unsigned haloed_id =
6211 flat_unsigned_receive_packed_data[iflat_packed];
6214 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6217 Node* haloed_face_node_pt = this->haloed_node_pt(ip, haloed_id);
6231 if (!done_haloed_face_node[haloed_face_node_pt])
6234 haloed_face_node_pt->set_coordinates_on_boundary(b, zeta);
6237 for (
unsigned iiproc = 0; iiproc < nproc; iiproc++)
6240 if (iiproc != my_rank)
6243 const unsigned nhaloed_node_iiproc = this->nhaloed_node(iiproc);
6244 for (
unsigned ihdn = 0; ihdn < nhaloed_node_iiproc; ihdn++)
6246 Node* compare_haloed_node_pt=this->haloed_node_pt(iiproc,ihdn);
6247 if (haloed_face_node_pt == compare_haloed_node_pt)
6251 face_haloed_node_pt[iiproc].push_back(haloed_face_node_pt);
6254 face_haloed_node_id[iiproc].push_back(ihdn);
6275 for (
unsigned ip = 0; ip < nproc; ip++)
6287 const unsigned nhaloed_face_nodes = face_haloed_node_pt[ip].size();
6289 for (
unsigned ihdfn = 0; ihdfn < nhaloed_face_nodes; ihdfn++)
6292 Node *haloed_face_node_pt = face_haloed_node_pt[ip][ihdfn];
6294 const unsigned haloed_id = face_haloed_node_id[ip][ihdfn];
6299 flat_unsigned_send_packed_data.push_back(haloed_id);
6300 flat_double_send_packed_data.push_back(zeta[0]);
6305 MPI_Request request;
6308 int send_proc =
static_cast<int>(ip);
6310 int receive_proc =
static_cast<int>(ip);
6318 unsigned nflat_unsigned_send = flat_unsigned_send_packed_data.size();
6319 MPI_Isend(&nflat_unsigned_send,1,MPI_UNSIGNED,
6320 send_proc,1,comm_pt->mpi_comm(),&request);
6322 unsigned nflat_unsigned_receive = 0;
6323 MPI_Recv(&nflat_unsigned_receive,1,MPI_UNSIGNED,
6324 receive_proc,1,comm_pt->mpi_comm(),&status);
6326 MPI_Wait(&request,MPI_STATUS_IGNORE);
6328 if (nflat_unsigned_send!=0)
6330 MPI_Isend(&flat_unsigned_send_packed_data[0],nflat_unsigned_send,
6331 MPI_UNSIGNED,send_proc,2,comm_pt->mpi_comm(),&request);
6334 if (nflat_unsigned_receive!=0)
6336 flat_unsigned_receive_packed_data.resize(nflat_unsigned_receive);
6337 MPI_Recv(&flat_unsigned_receive_packed_data[0],nflat_unsigned_receive,
6338 MPI_UNSIGNED,receive_proc,2,comm_pt->mpi_comm(),&status);
6341 if (nflat_unsigned_send!=0)
6343 MPI_Wait(&request,MPI_STATUS_IGNORE);
6348 unsigned nflat_double_send = flat_double_send_packed_data.size();
6349 MPI_Isend(&nflat_double_send,1,MPI_DOUBLE,
6350 send_proc,3,comm_pt->mpi_comm(),&request);
6352 unsigned nflat_double_receive = 0;
6353 MPI_Recv(&nflat_double_receive,1,MPI_DOUBLE,
6354 receive_proc,3,comm_pt->mpi_comm(),&status);
6356 MPI_Wait(&request,MPI_STATUS_IGNORE);
6358 if (nflat_double_send!=0)
6360 MPI_Isend(&flat_double_send_packed_data[0],nflat_double_send,
6361 MPI_DOUBLE,send_proc,4,comm_pt->mpi_comm(),&request);
6364 if (nflat_double_receive!=0)
6366 flat_double_receive_packed_data.resize(nflat_double_receive);
6367 MPI_Recv(&flat_double_receive_packed_data[0],nflat_double_receive,
6368 MPI_DOUBLE,receive_proc,4,comm_pt->mpi_comm(),&status);
6371 if (nflat_double_send!=0)
6373 MPI_Wait(&request,MPI_STATUS_IGNORE);
6378 if (nflat_unsigned_receive!=nflat_double_receive)
6380 std::ostringstream error_message;
6382 <<
"The number of unsigned received data ("
6383 << nflat_unsigned_receive <<
") is different from the "
6384 <<
"number\nof double received data ("
6385 << nflat_double_receive <<
")!!!\n\n";
6387 "TriangleMesh::synchronize_boundary_coordinates()",
6388 OOMPH_EXCEPTION_LOCATION);
6395 for (
unsigned iflat_packed = 0; iflat_packed < nflat_unsigned_receive;
6399 const unsigned halo_id =
6400 flat_unsigned_receive_packed_data[iflat_packed];
6403 zeta[0] = flat_double_receive_packed_data[iflat_packed];
6406 Node* halo_face_node_pt = this->halo_node_pt(ip, halo_id);
6423 for (
unsigned ie = 0; ie < nbound_ele; ie++)
6425 delete tmp_face_ele_pt[ie];
6426 tmp_face_ele_pt[ie] = 0;
6431 if (is_internal_boundary)
6433 re_scale_re_assigned_initial_zeta_values_for_internal_boundary(b);
6444 template<
class ELEMENT>
6462 unsigned n_repeated_ele = 0;
6464 const unsigned n_regions = this->nregion();
6473 for (
unsigned rr = 0 ; rr < n_regions; rr++)
6475 const unsigned region_id =
6476 static_cast<unsigned>(this->Region_attribute[rr]);
6479 const unsigned nel_in_region =
6480 this->nboundary_element_in_region(b, region_id);
6482 unsigned nel_repetead_in_region = 0;
6486 if (nel_in_region > 0)
6488 bool repeated =
false;
6491 for (
unsigned e = 0;
e < nel_in_region;
e++)
6496 this->boundary_element_in_region_pt(b, region_id,
e);
6507 this->face_index_at_boundary_in_region(b,region_id,
e);
6515 const unsigned n_nodes = tmp_ele_pt->
nnode();
6517 std::pair<Node*, Node*> tmp_pair =
6518 std::make_pair(tmp_ele_pt->
node_pt(0),
6519 tmp_ele_pt->
node_pt(n_nodes - 1));
6521 std::pair<Node*, Node*> tmp_pair_inverse =
6522 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
6526 const unsigned n_done_nodes = done_nodes_pt.size();
6527 for (
unsigned l = 0; l < n_done_nodes; l++)
6529 if (tmp_pair == done_nodes_pt[l] ||
6530 tmp_pair_inverse == done_nodes_pt[l])
6532 nel_repetead_in_region++;
6542 done_nodes_pt.push_back(tmp_pair);
6544 face_el_pt.push_back(tmp_ele_pt);
6558 nele += nel_in_region;
6560 n_repeated_ele += nel_repetead_in_region;
6569 nele = this->nboundary_element(b);
6575 bool repeated =
false;
6578 for (
unsigned e = 0;
e < nele;
e++)
6593 int face_index = this->face_index_at_boundary(b,
e);
6601 const unsigned n_nodes = tmp_ele_pt->
nnode();
6603 std::pair<Node*, Node*> tmp_pair =
6604 std::make_pair(tmp_ele_pt->
node_pt(0),
6605 tmp_ele_pt->
node_pt(n_nodes - 1));
6607 std::pair<Node*, Node*> tmp_pair_inverse =
6608 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
6612 const unsigned n_done_nodes = done_nodes_pt.size();
6613 for (
unsigned l = 0; l < n_done_nodes; l++)
6615 if (tmp_pair == done_nodes_pt[l] ||
6616 tmp_pair_inverse == done_nodes_pt[l])
6630 done_nodes_pt.push_back(tmp_pair);
6632 face_el_pt.push_back(tmp_ele_pt);
6650 nele-= n_repeated_ele;
6653 if (nele!=face_el_pt.size())
6655 std::ostringstream error_message;
6657 <<
"The independet counting of face elements ("<<nele<<
") for "
6658 <<
"boundary ("<<b<<
") is different\n"
6659 <<
"from the real number of face elements in the container ("
6660 << face_el_pt.size() <<
")\n";
6663 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6664 OOMPH_EXCEPTION_LOCATION);
6674 const unsigned nnon_halo_face_elements = face_el_pt.size();
6681 unsigned nsorted_face_elements = 0;
6684 std::map<FiniteElement*, bool> done_el;
6687 std::map<FiniteElement*, bool> is_inverted;
6690 while(nsorted_face_elements < nnon_halo_face_elements)
6694 std::list<FiniteElement*> sorted_el_pt;
6698 bool found_initial_face_element =
false;
6704 for (iface = 0; iface < nele; iface++)
6706 ele_face_pt = face_el_pt[iface];
6708 if (!done_el[ele_face_pt])
6711 found_initial_face_element =
true;
6713 nsorted_face_elements++;
6715 sorted_el_pt.push_back(ele_face_pt);
6717 done_el[ele_face_pt] =
true;
6723 if (!found_initial_face_element)
6725 std::ostringstream error_message;
6727 <<
"Could not find an initial face element for the current segment\n";
6730 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6731 OOMPH_EXCEPTION_LOCATION);
6736 const unsigned nnod = ele_face_pt->
nnode();
6741 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
6745 bool face_element_added =
false;
6754 for (
unsigned iiface = iface; iiface < nele; iiface++)
6757 face_element_added =
false;
6760 ele_face_pt = face_el_pt[iiface];
6763 if (!(done_el[ele_face_pt]))
6766 Node* local_left_node_pt = ele_face_pt->node_pt(0);
6767 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
6770 if (left_node_pt == local_right_node_pt)
6772 left_node_pt = local_left_node_pt;
6773 sorted_el_pt.push_front(ele_face_pt);
6774 is_inverted[ele_face_pt] =
false;
6775 face_element_added =
true;
6778 else if (left_node_pt == local_left_node_pt)
6780 left_node_pt = local_right_node_pt;
6781 sorted_el_pt.push_front(ele_face_pt);
6782 is_inverted[ele_face_pt] =
true;
6783 face_element_added =
true;
6786 else if (right_node_pt == local_left_node_pt)
6788 right_node_pt = local_right_node_pt;
6789 sorted_el_pt.push_back(ele_face_pt);
6790 is_inverted[ele_face_pt] =
false;
6791 face_element_added =
true;
6794 else if (right_node_pt == local_right_node_pt)
6796 right_node_pt = local_left_node_pt;
6797 sorted_el_pt.push_back(ele_face_pt);
6798 is_inverted[ele_face_pt] =
true;
6799 face_element_added =
true;
6802 if (face_element_added)
6804 done_el[ele_face_pt] =
true;
6805 nsorted_face_elements++;
6811 }
while(face_element_added &&
6812 (nsorted_face_elements < nnon_halo_face_elements));
6815 segment_sorted_ele_pt.push_back(sorted_el_pt);
6831 const unsigned nsegments = segment_sorted_ele_pt.size();
6834 if (nnon_halo_face_elements > 0 && nsegments == 0)
6836 std::ostringstream error_message;
6838 <<
"The number of segments is zero, but the number of nonhalo\n"
6839 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
6841 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6842 OOMPH_EXCEPTION_LOCATION);
6857 for (
unsigned is = 0; is < nsegments; is++)
6860 if (segment_sorted_ele_pt[is].size() == 0)
6862 std::ostringstream error_message;
6864 <<
"The (" << is <<
")-th segment has no elements\n";
6866 "TriangleMesh::re_scale_re_assigned_initial_zeta_values_for_internal_boundary()",
6867 OOMPH_EXCEPTION_LOCATION);
6872 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
6875 const unsigned nnod = first_ele_pt->
nnode();
6879 if (is_inverted[first_ele_pt])
6881 first_node_pt = first_ele_pt->node_pt(nnod-1);
6885 FiniteElement* last_ele_pt = segment_sorted_ele_pt[is].back();
6888 Node *last_node_pt = last_ele_pt->
node_pt(nnod-1);
6889 if (is_inverted[last_ele_pt])
6891 last_node_pt = last_ele_pt->node_pt(0);
6895 double x_left = first_node_pt->
x(0);
6896 double y_left = first_node_pt->
x(1);
6905 if (this->boundary_geom_object_pt(b)!=0)
6908 initial_zeta_segment[is] = zeta[0];
6910 final_zeta_segment[is] = zeta[0];
6914 std::set<Node*> local_nodes_pt;
6915 local_nodes_pt.insert(first_node_pt);
6918 for (std::list<FiniteElement*>::iterator it =
6919 segment_sorted_ele_pt[is].begin();
6920 it != segment_sorted_ele_pt[is].end(); it++)
6928 if (is_inverted[el_pt])
6935 for (
unsigned j = 1; j < nnod; j++)
6937 Node* nod_pt = el_pt->node_pt(k_nod);
6941 double x_right = nod_pt->
x(0);
6942 double y_right = nod_pt->
x(1);
6946 (x_right - x_left) * (x_right - x_left) + (y_right - y_left)
6947 * (y_right - y_left));
6955 local_nodes_pt.insert(nod_pt);
6961 segment_arclength[is] = zeta[0];
6964 segment_all_nodes_pt.push_back(local_nodes_pt);
6976 Boundary_segment_inverted[b].clear();
6977 Boundary_segment_initial_coordinate[b].clear();
6978 Boundary_segment_final_coordinate[b].clear();
6980 Boundary_segment_initial_zeta[b].clear();
6981 Boundary_segment_final_zeta[b].clear();
6983 Boundary_segment_initial_arclength[b].clear();
6984 Boundary_segment_final_arclength[b].clear();
6989 first_node_zeta_coordinate = boundary_initial_zeta_coordinate(b);
6990 last_node_zeta_coordinate = boundary_final_zeta_coordinate(b);
6993 const double boundary_arclength =
6994 std::max(first_node_zeta_coordinate[0], last_node_zeta_coordinate[0]);
6998 for (
unsigned is = 0; is < nsegments; is++)
7001 FiniteElement* first_face_ele_pt = segment_sorted_ele_pt[is].front();
7004 const unsigned nnod = first_face_ele_pt->
nnode();
7007 Node* first_node_pt = first_face_ele_pt->
node_pt(0);
7008 if (is_inverted[first_face_ele_pt])
7010 first_node_pt = first_face_ele_pt->node_pt(nnod-1);
7018 FiniteElement* last_face_ele_pt = segment_sorted_ele_pt[is].back();
7021 Node* last_node_pt = last_face_ele_pt->
node_pt(nnod-1);
7022 if (is_inverted[last_face_ele_pt])
7024 last_node_pt = last_face_ele_pt->node_pt(0);
7035 for (
unsigned i = 0;
i < 2;
i++)
7037 first_node_coord[
i] = first_node_pt->
x(
i);
7038 last_node_coord[
i] = last_node_pt->
x(
i);
7042 Boundary_segment_inverted[b].push_back(0);
7043 Boundary_segment_initial_coordinate[b].push_back(first_node_coord);
7044 Boundary_segment_final_coordinate[b].push_back(last_node_coord);
7047 if (this->boundary_geom_object_pt(b)!=0)
7049 Boundary_segment_initial_zeta[b].push_back(zeta_first[0]);
7050 Boundary_segment_final_zeta[b].push_back(zeta_last[0]);
7055 Boundary_segment_initial_arclength[b].push_back(
7056 zeta_first[0] * boundary_arclength);
7057 Boundary_segment_final_arclength[b].push_back(
7058 zeta_last[0] * boundary_arclength);
7064 for (
unsigned i = 0;
i < nele;
i++)
7066 delete face_el_pt[
i];
7072 #endif // OOMPH_HAS_MPI
7076 #ifdef OOMPH_HAS_TRIANGLE_LIB
7081 template <
class ELEMENT>
7085 bool &use_attributes)
7090 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
7094 OOMPH_CURRENT_FUNCTION,
7095 OOMPH_EXCEPTION_LOCATION);
7102 poly_file.ignore(80,
'\n');
7105 unsigned invertices;
7106 poly_file>>invertices;
7111 (
double *) malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
7115 poly_file>>mesh_dim;
7126 OOMPH_CURRENT_FUNCTION,
7127 OOMPH_EXCEPTION_LOCATION);
7133 poly_file>> nextras;
7139 unsigned nodemarkers;
7140 poly_file>>nodemarkers;
7146 if(nextras!=0 || nodemarkers!=0)
7148 oomph_info <<
"===================================================="
7149 << std::endl<<std::endl;
7150 oomph_info <<
"Reading the .poly file via oomph_lib \n"
7151 <<
"point's attribute and point's markers \n"
7152 <<
"are automatically set to 0"<<std::endl;
7153 oomph_info <<
"===================================================="
7159 unsigned dummy_value;
7160 unsigned count_point=0;
7164 getline(poly_file,test_string,
'#');
7165 poly_file.ignore(80,
'\n');
7169 for(
unsigned count=0;count<invertices;count++)
7171 poly_file>>dummy_value;
7172 poly_file>>triangulate_io.
pointlist[count_point];
7173 poly_file>>triangulate_io.
pointlist[count_point+1];
7174 if(nextras!=0 || nodemarkers!=0)
7176 for(
unsigned j=0;j<nextras;j++)
7178 poly_file>>dummy_value;
7181 else if(nextras!=0 && nodemarkers!=0)
7183 for(
unsigned j=0;j<nextras;j++)
7185 poly_file>>dummy_value;
7186 poly_file>>dummy_value;
7190 poly_file.ignore(80,
'\n');
7193 if(poly_file.get() ==
'#')
7195 poly_file.ignore(80,
'\n');
7211 unsigned inelements;
7212 poly_file>>inelements;
7214 unsigned segment_markers;
7215 poly_file>>segment_markers;
7220 if(segment_markers!=1)
7223 std::ostringstream error_stream;
7225 <<
"The segment marker should be provided \n"
7226 <<
"In order to assign each segment to a boundary \n "<< std::endl;
7229 OOMPH_CURRENT_FUNCTION,
7230 OOMPH_EXCEPTION_LOCATION);
7241 for(
unsigned i=0;
i<2*inelements;
i+=2)
7243 poly_file>>dummy_seg;
7246 if(segment_markers!=0)
7252 poly_file.ignore(80,
'\n');
7257 if(getline(poly_file,test_string,
'#'))
7259 poly_file.ignore(80,
'\n');
7261 unsigned dummy_hole;
7267 (
double *) malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
7271 for(
unsigned i=0;
i<2*nhole;
i+=2)
7273 poly_file>>dummy_hole;
7275 poly_file>>triangulate_io.
holelist[
i+1];
7281 if(getline(poly_file,test_string,
'#'))
7283 poly_file.ignore(80,
'\n');
7285 unsigned dummy_region;
7288 std::cerr <<
"Regions: "<< nregion << std::endl;
7293 (
double *) malloc(triangulate_io.
numberofregions * 4 *
sizeof(
double));
7297 {use_attributes=
true;}
7301 for(
unsigned i=0;
i<nregion;
i++)
7303 poly_file>>dummy_region;
7315 #ifdef OOMPH_HAS_TRIANGLE_LIB
7316 #ifdef OOMPH_HAS_MPI
7321 template<
class ELEMENT>
7326 if (this->is_mesh_distributed())
7329 const unsigned nboundary = this->nboundary();
7330 dump_file << nboundary
7331 <<
" # number of original boundaries" << std::endl;
7334 const unsigned nshared_boundaries = this->nshared_boundaries();
7335 dump_file << nshared_boundaries
7336 <<
" # number of shared boundaries" << std::endl;
7339 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
7340 dump_file << init_shd_bnd_id
7341 <<
" # initial shared boundaries id" << std::endl;
7343 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
7344 dump_file << final_shd_bnd_id
7345 <<
" # final shared boundaries id" << std::endl;
7348 const unsigned nprocs = this->shared_boundaries_ids().size();
7349 dump_file << nprocs <<
" # number of processors" << std::endl;
7353 for (
unsigned ip = 0; ip < nprocs; ip++)
7355 for (
unsigned jp = 0; jp < nprocs; jp++)
7361 const unsigned nshared_boundaries_iproc_jproc =
7362 this->shared_boundaries_ids(ip, jp).size();
7366 dump_file << nshared_boundaries_iproc_jproc
7367 <<
" # number of shared boundaries with in two "
7368 <<
"processors" << std::endl;
7369 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7371 const unsigned shared_boundary_id =
7372 this->shared_boundaries_ids(ip, jp, is);
7373 dump_file << ip <<
" " << jp <<
" " << shared_boundary_id
7374 <<
" # ip jp shared_boundary of processors ip and jp"
7387 const unsigned nshared_boundaries_overlap_internal_boundaries =
7388 this->nshared_boundary_overlaps_internal_boundary();
7389 dump_file << nshared_boundaries_overlap_internal_boundaries
7390 <<
" # number of shared boundaries that overlap internal "
7391 <<
"boundaries" << std::endl;
7393 if (nshared_boundaries_overlap_internal_boundaries > 0)
7395 for (
unsigned isb = init_shd_bnd_id; isb < final_shd_bnd_id; isb++)
7399 if (this->shared_boundary_overlaps_internal_boundary(isb))
7403 const unsigned overlapped_internal_boundary =
7404 shared_boundary_overlapping_internal_boundary(isb);
7406 dump_file << isb <<
" " << overlapped_internal_boundary
7407 <<
" # the shared boundary overlaps the internal "
7408 <<
"boundary " << std::endl;
7419 for (
unsigned b = 0; b < nboundary; b++)
7424 if (Assigned_segments_initial_zeta_values[b])
7428 dump_file <<
"1 # assigned boundary coordinates initial zeta values"
7435 Vector<double> initial_coordinates=this->boundary_initial_coordinate(b);
7437 Vector<double> final_coordinates=this->boundary_final_coordinate(b);
7439 dump_file << std::setprecision(14)
7440 << initial_coordinates[0] <<
" " << initial_coordinates[1]
7441 <<
" # initial coordinates for the current boundary"
7444 dump_file << std::setprecision(14)
7445 << final_coordinates[0] <<
" " << final_coordinates[1]
7446 <<
" # final coordinates for the current boundary"
7453 const unsigned zeta_size =
7454 this->boundary_initial_zeta_coordinate(b).size();
7458 std::ostringstream error_message;
7460 <<
"The dimension for the zeta values container is different\n"
7461 <<
"from 1, the current implementation only supports\n"
7462 <<
"one-dimensioned zeta containers\n\n";
7464 "TriangleMesh::dump_distributed_info_for_restart()",
7465 OOMPH_EXCEPTION_LOCATION);
7469 Vector<double> zeta_initial = this->boundary_initial_zeta_coordinate(b);
7470 Vector<double> zeta_final = this->boundary_final_zeta_coordinate(b);
7472 dump_file << std::setprecision(14)
7474 <<
" # initial zeta value for the current boundary"
7477 dump_file << std::setprecision(14)
7479 <<
" # final zeta value for the current boundary"
7483 const unsigned nsegments = this->nboundary_segment(b);
7485 dump_file << b <<
" " << nsegments
7486 <<
" # of segments for the current boundary"
7490 for (
unsigned is = 0; is < nsegments; is++)
7494 this->boundary_segment_initial_coordinate(b)[is];
7496 this->boundary_segment_final_coordinate(b)[is];
7498 dump_file << std::setprecision(14)
7499 << initial_segment_coordinates[0] <<
" "
7500 << initial_segment_coordinates[1]
7501 <<
" # initial segment coordinates for the current boundary"
7504 dump_file << std::setprecision(14)
7505 << final_segment_coordinates[0] <<
" "
7506 << final_segment_coordinates[1]
7507 <<
" # final segment coordinates for the current boundary"
7512 if (this->boundary_geom_object_pt(b)!=0)
7514 const double zeta_segment_initial =
7515 this->boundary_segment_initial_zeta(b)[is];
7516 const double zeta_segment_final =
7517 this->boundary_segment_final_zeta(b)[is];
7519 dump_file << std::setprecision(14)
7520 << zeta_segment_initial
7521 <<
" # initial segment zeta value for the current boundary"
7524 dump_file << std::setprecision(14)
7525 << zeta_segment_final
7526 <<
" # final segment zeta value for the current boundary"
7531 const double arclength_segment_initial =
7532 this->boundary_segment_initial_arclength(b)[is];
7533 const double arclength_segment_final =
7534 this->boundary_segment_final_arclength(b)[is];
7536 dump_file << std::setprecision(14)
7537 << arclength_segment_initial
7538 <<
" # initial segment arclength for the current boundary"
7541 dump_file << std::setprecision(14)
7542 << arclength_segment_final
7543 <<
" # final segment arclength for the current boundary"
7555 dump_file <<
"0 # assigned boundary coordinates initial zeta values"
7568 template<
class ELEMENT>
7573 if (this->is_mesh_distributed())
7576 const unsigned n_boundary = read_unsigned_line_helper(restart_file);
7579 if (n_boundary != this->nboundary())
7581 std::ostringstream error_message;
7583 <<
"The number of boundaries (" << n_boundary <<
") on the "
7584 <<
"file used for restarting is different\nfrom the number of "
7585 <<
"boundaries ("<< this->nboundary() <<
") on the current "
7588 "TriangleMesh::read_distributed_info_for_restart()",
7589 OOMPH_EXCEPTION_LOCATION);
7594 unsigned n_shared_boundaries =
7595 read_unsigned_line_helper(restart_file);
7598 n_shared_boundaries++;
7599 n_shared_boundaries--;
7602 unsigned init_shd_bnd_id = read_unsigned_line_helper(restart_file);
7608 unsigned final_shd_bnd_id = read_unsigned_line_helper(restart_file);
7616 const unsigned n_procs = read_unsigned_line_helper(restart_file);
7619 if (
static_cast<int>(n_procs) != this->communicator_pt()->nproc())
7621 std::ostringstream error_message;
7623 <<
"The number of previously used processors ("<< n_procs
7624 <<
") (read from the restart file) is different\nfrom the "
7625 <<
"number of current used processors ("
7626 << this->communicator_pt()->nproc() <<
")\n\n";
7628 "TriangleMesh::read_distributed_info_for_restart()",
7629 OOMPH_EXCEPTION_LOCATION);
7634 this->shared_boundaries_ids().clear();
7635 this->shared_boundary_from_processors().clear();
7636 this->shared_boundary_overlaps_internal_boundary().clear();
7640 this->shared_boundaries_ids().resize(n_procs);
7644 for (
unsigned ip = 0; ip < n_procs; ip++)
7648 this->shared_boundaries_ids(ip).resize(n_procs);
7649 for (
unsigned jp = 0; jp < n_procs; jp++)
7655 const unsigned nshared_boundaries_iproc_jproc =
7656 read_unsigned_line_helper(restart_file);
7657 for (
unsigned is = 0; is < nshared_boundaries_iproc_jproc; is++)
7661 restart_file >> tmp_ip;
7663 restart_file >> tmp_jp;
7667 const unsigned shared_boundary_id =
7668 read_unsigned_line_helper(restart_file);
7672 this->shared_boundaries_ids(ip, jp).
7673 push_back(shared_boundary_id);
7680 this->shared_boundary_from_processors()[shared_boundary_id] =
7693 const unsigned nshared_boundaries_overlap_internal_boundaries =
7694 read_unsigned_line_helper(restart_file);
7696 for (
unsigned isb = 0;
7697 isb < nshared_boundaries_overlap_internal_boundaries;
7701 unsigned shared_boundary_overlapping;
7702 restart_file >> shared_boundary_overlapping;
7704 const unsigned overlapped_internal_boundary =
7705 read_unsigned_line_helper(restart_file);
7709 this->shared_boundary_overlaps_internal_boundary()
7710 [shared_boundary_overlapping] = overlapped_internal_boundary;
7718 for (
unsigned b = 0; b < n_boundary; b++)
7722 const unsigned boundary_coordinates_initial_zeta_values_assigned =
7723 read_unsigned_line_helper(restart_file);
7725 if (boundary_coordinates_initial_zeta_values_assigned)
7730 Boundary_initial_coordinate[b].clear();
7731 Boundary_final_coordinate[b].clear();
7733 Boundary_initial_zeta_coordinate[b].clear();
7734 Boundary_final_zeta_coordinate[b].clear();
7737 Boundary_segment_inverted[b].clear();
7738 Boundary_segment_initial_coordinate[b].clear();
7739 Boundary_segment_final_coordinate[b].clear();
7741 Boundary_segment_initial_zeta[b].clear();
7742 Boundary_segment_final_zeta[b].clear();
7744 Boundary_segment_initial_arclength[b].clear();
7745 Boundary_segment_final_arclength[b].clear();
7754 restart_file >> initial_coordinates[0] >> initial_coordinates[1];
7757 restart_file.ignore(80,
'\n');
7762 restart_file >> final_coordinates[0] >> final_coordinates[1];
7765 restart_file.ignore(80,
'\n');
7770 this->boundary_initial_coordinate(b)=initial_coordinates;
7771 this->boundary_final_coordinate(b)=final_coordinates;
7775 restart_file >> zeta_initial[0];
7778 restart_file.ignore(80,
'\n');
7781 restart_file >> zeta_final[0];
7784 restart_file.ignore(80,
'\n');
7787 this->boundary_initial_zeta_coordinate(b) = zeta_initial;
7788 this->boundary_final_zeta_coordinate(b) = zeta_final;
7791 unsigned current_boundary;
7792 restart_file >> current_boundary;
7795 if (current_boundary != b)
7797 std::ostringstream error_message;
7799 <<
"The current boundary id from the restart file ("
7800 << current_boundary <<
") is different from\nthe boundary id "
7801 << b <<
"currently used to re-establish the initial and\nfinal "
7802 <<
"segment's zeta values\n\n";
7804 "TriangleMesh::read_distributed_info_for_restart()",
7805 OOMPH_EXCEPTION_LOCATION);
7811 restart_file >> nsegments;
7814 restart_file.ignore(80,
'\n');
7819 for (
unsigned is = 0; is < nsegments; is++)
7825 restart_file >> initial_segment_coordinates[0]
7826 >> initial_segment_coordinates[1];
7829 restart_file.ignore(80,
'\n');
7834 restart_file >> final_segment_coordinates[0]
7835 >> final_segment_coordinates[1];
7838 restart_file.ignore(80,
'\n');
7841 this->boundary_segment_initial_coordinate(b).push_back(
7842 initial_segment_coordinates);
7843 this->boundary_segment_final_coordinate(b).push_back(
7844 final_segment_coordinates);
7847 if (this->boundary_geom_object_pt(b)!=0)
7850 restart_file >> zeta_segment_initial[0];
7853 restart_file.ignore(80,
'\n');
7856 restart_file >> zeta_segment_final[0];
7859 restart_file.ignore(80,
'\n');
7862 this->boundary_segment_initial_zeta(b).push_back(
7863 zeta_segment_initial[0]);
7864 this->boundary_segment_final_zeta(b).push_back(
7865 zeta_segment_final[0]);
7870 restart_file >> arclength_segment_initial[0];
7873 restart_file.ignore(80,
'\n');
7876 restart_file >> arclength_segment_final[0];
7879 restart_file.ignore(80,
'\n');
7882 this->boundary_segment_initial_arclength(b).push_back(
7883 arclength_segment_initial[0]);
7884 this->boundary_segment_final_arclength(b).push_back(
7885 arclength_segment_final[0]);
7898 #endif // #ifdef OOMPH_HAS_MPI
7899 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB
7905 template<
class ELEMENT>
7907 std::ostream &outfile)
7916 std::set<Node*> boundary_nodes_pt;
7917 const unsigned n_boundary_ele = this->nboundary_element(b);
7918 for (
unsigned e = 0;
e < n_boundary_ele;
e++)
7922 #ifdef OOMPH_HAS_MPI
7928 int face_index = this->face_index_at_boundary(b,
e);
7931 bulk_ele_pt, face_index);
7934 const unsigned n_nodes = face_ele_pt->
nnode();
7935 for (
unsigned i = 0;
i < n_nodes;
i++)
7940 boundary_nodes_pt.insert(tmp_node_pt);
7946 #ifdef OOMPH_HAS_MPI
7952 outfile <<
"ZONE T=\"Boundary nodes" << b <<
"\"\n";
7954 std::set<Vector<double> > set_node_coord;
7956 for (std::set<Node*>::iterator it = boundary_nodes_pt.begin();
7957 it != boundary_nodes_pt.end(); it++)
7959 Node *inode_pt = (*it);
7962 const unsigned n_dim = inode_pt->
ndim();
7968 node_coord[0] = zeta[0];
7969 for (
unsigned j = 0; j < n_dim; j++)
7971 node_coord[j+1] = inode_pt->
x(j);
7973 set_node_coord.insert(node_coord);
7976 for (std::set<
Vector<double> >::iterator it = set_node_coord.begin();
7977 it != set_node_coord.end(); it++)
7983 const unsigned n_dim = node_coord.size()-1;
7984 for (
unsigned j = 0; j < n_dim; j++)
7986 outfile << node_coord[j+1] <<
" ";
7989 outfile <<
"0.0" << std::endl;
7993 outfile <<
"ZONE T=\"Boundary coordinates " << b <<
"\"\n";
7994 for (std::set<
Vector<double> >::iterator it = set_node_coord.begin();
7995 it != set_node_coord.end(); it++)
8001 const unsigned n_dim = node_coord.size()-1;
8002 for (
unsigned j = 0; j < n_dim; j++)
8004 outfile << node_coord[j+1] <<
" ";
8008 outfile << node_coord[0] << std::endl;
8013 #ifdef OOMPH_HAS_MPI
8020 template<
class ELEMENT>
8031 const unsigned my_rank = this->communicator_pt()->my_rank();
8053 const unsigned nouter=this->Outer_boundary_pt.size();
8054 for (
unsigned i = 0;
i < nouter;
i++)
8056 const unsigned npolylines = this->Outer_boundary_pt[
i]->npolyline();
8057 for (
unsigned p = 0; p < npolylines; p++)
8061 this->Outer_boundary_pt[
i]->polyline_pt(p);
8062 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8068 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8069 if (!boundary_was_splitted(bound_id))
8071 unsorted_outer_polyline_pt.push_back(tmp_polyline_pt);
8077 boundary_subpolylines(bound_id);
8078 const unsigned nsub_poly = tmp_vector_polylines.size();
8082 std::ostringstream error_message;
8084 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8085 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8087 OOMPH_CURRENT_FUNCTION,
8088 OOMPH_EXCEPTION_LOCATION);
8093 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8095 unsorted_outer_polyline_pt.push_back(tmp_vector_polylines[isub]);
8097 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8100 std::ostringstream error_message;
8102 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8103 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8105 OOMPH_CURRENT_FUNCTION,
8106 OOMPH_EXCEPTION_LOCATION);
8108 #endif // #ifdef PARANOID
8116 unsigned nunsorted_outer_polyline = unsorted_outer_polyline_pt.size();
8117 if (nunsorted_outer_polyline > 0)
8122 sort_polylines_helper(unsorted_outer_polyline_pt, sorted_outer_curves_pt);
8141 const unsigned ninternal_closed=this->Internal_polygon_pt.size();
8142 for (
unsigned i = 0;
i < ninternal_closed;
i++)
8144 const unsigned npolylines = this->Internal_polygon_pt[
i]->npolyline();
8145 for (
unsigned p = 0; p < npolylines; p++)
8149 this->Internal_polygon_pt[
i]->polyline_pt(p);
8150 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8156 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8157 if (!boundary_was_splitted(bound_id))
8159 unsorted_internal_closed_polyline_pt.push_back(tmp_polyline_pt);
8165 boundary_subpolylines(bound_id);
8166 const unsigned nsub_poly = tmp_vector_polylines.size();
8170 std::ostringstream error_message;
8172 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8173 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8175 OOMPH_CURRENT_FUNCTION,
8176 OOMPH_EXCEPTION_LOCATION);
8181 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8183 unsorted_internal_closed_polyline_pt.push_back(tmp_vector_polylines[isub]);
8185 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8188 std::ostringstream error_message;
8190 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8191 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8193 OOMPH_CURRENT_FUNCTION,
8194 OOMPH_EXCEPTION_LOCATION);
8196 #endif // #ifdef PARANOID
8203 const unsigned nunsorted_internal_closed_polyline =
8204 unsorted_internal_closed_polyline_pt.size();
8206 if (nunsorted_internal_closed_polyline > 0)
8210 sort_polylines_helper(unsorted_internal_closed_polyline_pt,
8211 sorted_internal_closed_curves_pt);
8229 const unsigned ninternal_open = this->Internal_open_curve_pt.size();
8230 for (
unsigned i = 0;
i < ninternal_open;
i++)
8232 const unsigned ncurve_section =
8233 this->Internal_open_curve_pt[
i]->ncurve_section();
8234 for (
unsigned p = 0; p < ncurve_section; p++)
8238 this->Internal_open_curve_pt[
i]->polyline_pt(p);
8239 const unsigned nvertex = tmp_polyline_pt->
nvertex();
8245 const unsigned bound_id = tmp_polyline_pt->
boundary_id();
8246 if (!boundary_was_splitted(bound_id))
8250 if (!boundary_marked_as_shared_boundary(bound_id, 0))
8252 unsorted_internal_open_polyline_pt.push_back(tmp_polyline_pt);
8259 boundary_subpolylines(bound_id);
8260 const unsigned nsub_poly = tmp_vector_polylines.size();
8264 std::ostringstream error_message;
8266 <<
"The boundary ("<<bound_id<<
") was marked to be splitted but\n"
8267 <<
"there are only ("<<nsub_poly<<
") polylines to represent it.\n";
8269 OOMPH_CURRENT_FUNCTION,
8270 OOMPH_EXCEPTION_LOCATION);
8275 for (
unsigned isub = 0; isub < nsub_poly; isub++)
8279 if (!boundary_marked_as_shared_boundary(bound_id, isub))
8281 unsorted_internal_open_polyline_pt.push_back(tmp_vector_polylines[isub]);
8284 const unsigned nsvertex = tmp_vector_polylines[isub]->nvertex();
8287 std::ostringstream error_message;
8289 <<
"The current chunk ("<< isub <<
") of the polyline with\n"
8290 <<
"boundary id (" << bound_id <<
") has no vertices\n";
8292 OOMPH_CURRENT_FUNCTION,
8293 OOMPH_EXCEPTION_LOCATION);
8295 #endif // #ifdef PARANOID
8302 const unsigned nunsorted_internal_open_polyline =
8303 unsorted_internal_open_polyline_pt.size();
8305 if (nunsorted_internal_open_polyline > 0)
8309 sort_polylines_helper(unsorted_internal_open_polyline_pt,
8310 sorted_internal_open_curves_pt);
8330 const unsigned ncurves = nshared_boundary_curves(my_rank);
8331 for (
unsigned i = 0;
i < ncurves;
i++)
8333 const unsigned npolylines = nshared_boundary_polyline(my_rank,
i);
8334 for (
unsigned p = 0; p < npolylines; p++)
8336 const unsigned nvertex =
8337 shared_boundary_polyline_pt(my_rank,
i, p)->nvertex();
8341 shared_boundary_polyline_pt(my_rank,
i, p);
8345 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
8348 const unsigned shd_bnd_id = tmp_shared_poly_pt->
boundary_id();
8352 if (this->shared_boundary_overlaps_internal_boundary(shd_bnd_id))
8354 unsorted_shared_to_internal_polyline_pt.push_back(
8355 tmp_shared_poly_pt);
8358 unsorted_shared_polyline_pt.push_back(tmp_shared_poly_pt);
8364 const unsigned nunsorted_shared_polyline =
8365 unsorted_shared_polyline_pt.size();
8367 if (nunsorted_shared_polyline > 0)
8371 sort_polylines_helper(unsorted_shared_polyline_pt, sorted_shared_curves_pt);
8381 const unsigned nouter_curves = sorted_outer_curves_pt.size();
8382 const unsigned ninternal_closed_curves =
8383 sorted_internal_closed_curves_pt.size();
8384 const unsigned nshared_curves = sorted_shared_curves_pt.size();
8385 const unsigned ntotal_curves = nouter_curves +
8386 ninternal_closed_curves +
8390 unsigned counter = 0;
8395 for (
unsigned i = 0;
i < nshared_curves;
i++,counter++)
8397 all_curves_pt[counter] = sorted_shared_curves_pt[
i];
8401 for (
unsigned i = 0;
i < ninternal_closed_curves;
i++,counter++)
8403 all_curves_pt[counter] = sorted_internal_closed_curves_pt[
i];
8407 for (
unsigned i = 0;
i < nouter_curves;
i++,counter++)
8409 all_curves_pt[counter] = sorted_outer_curves_pt[
i];
8414 this->create_tmp_polygons_helper(all_curves_pt,polygons_pt);
8416 this->create_tmp_open_curves_helper(sorted_internal_open_curves_pt,
8417 unsorted_shared_to_internal_polyline_pt,
8431 this->create_shared_polylines_connections();
8448 const unsigned n_holes = this->Internal_polygon_pt.size();
8449 for (
unsigned h = 0; h < n_holes; h++)
8452 this->Internal_polygon_pt[h]->internal_point();
8454 if (!hole_coordinates.empty())
8456 new_holes_coordinates.push_back(hole_coordinates);
8462 if (First_time_compute_holes_left_by_halo_elements)
8465 const unsigned n_extra_holes = Extra_holes_coordinates.size();
8466 for (
unsigned h = 0; h < n_extra_holes; h++)
8469 new_holes_coordinates.push_back(hole_coordinates);
8473 Original_extra_holes_coordinates = Extra_holes_coordinates;
8476 First_time_compute_holes_left_by_halo_elements =
false;
8483 const unsigned n_original_extra_holes =
8484 Original_extra_holes_coordinates.size();
8485 for (
unsigned h = 0; h < n_original_extra_holes; h++)
8487 Vector<double> hole_coordinates = Original_extra_holes_coordinates[h];
8488 new_holes_coordinates.push_back(hole_coordinates);
8494 compute_holes_left_by_halo_elements_helper(new_holes_coordinates);
8498 update_holes_information_helper(polygons_pt, new_holes_coordinates);
8504 Extra_holes_coordinates = new_holes_coordinates;
8517 template<
class ELEMENT>
8533 const unsigned ncurves = polylines_pt.size();
8536 const unsigned nunsorted_curves = ncurves;
8538 unsigned nsorted_curves = 0;
8541 std::vector<bool> done_curve(ncurves);
8546 std::list<Vector<TriangleMeshPolyLine*> > list_building_polygon_pt;
8549 bool root_curve_found =
false;
8554 unsigned root_curve_idx = 0;
8557 for (
unsigned ic = 0; ic < ncurves; ic++)
8559 if (!done_curve[ic])
8561 root_curve_idx = ic;
8564 root_curve_found =
true;
8566 done_curve[ic] =
true;
8573 if (!root_curve_found)
8575 std::stringstream err;
8576 err <<
"The root curve to create a polygon from the shared and "
8577 <<
"original boundaries was not found!!!\n";
8579 "TriangleMesh::create_tmp_polygons_helper()",
8580 OOMPH_EXCEPTION_LOCATION);
8588 list_building_polygon_pt.push_back(root_curve_pt);
8595 const unsigned nroot_curve_polyline = root_curve_pt.size();
8597 root_curve_pt[0]->initial_vertex_coordinate(root_curve_initial_vertex);
8598 root_curve_pt[nroot_curve_polyline-1]->
8599 final_vertex_coordinate(root_curve_final_vertex);
8603 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8604 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8606 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8607 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8614 curve_section_pt(nroot_curve_polyline);
8617 for (
unsigned i = 0;
i < nroot_curve_polyline;
i++)
8618 {curve_section_pt[
i] = root_curve_pt[
i];}
8625 this->Free_polygon_pt.insert(new_polygon_pt);
8628 polygons_pt.push_back(new_polygon_pt);
8635 bool added_curve =
false;
8640 bool polygon_created =
false;
8644 added_curve =
false;
8647 for (
unsigned ic = root_curve_idx+1; ic < ncurves; ic++)
8649 if (!done_curve[ic])
8657 const unsigned ncurrent_curve_polyline = current_curve_pt.size();
8664 current_curve_pt[0]->
8665 initial_vertex_coordinate(current_curve_initial_vertex);
8666 current_curve_pt[ncurrent_curve_polyline-1]->
8667 final_vertex_coordinate(current_curve_final_vertex);
8673 ((current_curve_final_vertex[0] - root_curve_initial_vertex[0])*
8674 (current_curve_final_vertex[0] - root_curve_initial_vertex[0]))
8676 ((current_curve_final_vertex[1] - root_curve_initial_vertex[1])*
8677 (current_curve_final_vertex[1] - root_curve_initial_vertex[1]));
8683 list_building_polygon_pt.push_front(current_curve_pt);
8685 done_curve[ic] =
true;
8687 root_curve_initial_vertex[0] = current_curve_initial_vertex[0];
8688 root_curve_initial_vertex[1] = current_curve_initial_vertex[1];
8697 ((current_curve_initial_vertex[0] - root_curve_initial_vertex[0])*
8698 (current_curve_initial_vertex[0] - root_curve_initial_vertex[0]))
8700 ((current_curve_initial_vertex[1] - root_curve_initial_vertex[1])*
8701 (current_curve_initial_vertex[1] - root_curve_initial_vertex[1]));
8707 tmp_curve_pt(ncurrent_curve_polyline);
8709 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8711 current_curve_pt[it]->reverse();
8712 tmp_curve_pt[it] = current_curve_pt[it];
8716 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--,count++)
8717 {current_curve_pt[count] = tmp_curve_pt[
i];}
8719 list_building_polygon_pt.push_front(current_curve_pt);
8721 done_curve[ic] =
true;
8723 root_curve_initial_vertex[0] = current_curve_final_vertex[0];
8724 root_curve_initial_vertex[1] = current_curve_final_vertex[1];
8733 ((current_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8734 (current_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8736 ((current_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8737 (current_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8743 list_building_polygon_pt.push_back(current_curve_pt);
8745 done_curve[ic] =
true;
8747 root_curve_final_vertex[0] = current_curve_final_vertex[0];
8748 root_curve_final_vertex[1] = current_curve_final_vertex[1];
8757 ((current_curve_final_vertex[0] - root_curve_final_vertex[0])*
8758 (current_curve_final_vertex[0] - root_curve_final_vertex[0]))
8760 ((current_curve_final_vertex[1] - root_curve_final_vertex[1])*
8761 (current_curve_final_vertex[1] - root_curve_final_vertex[1]));
8767 tmp_curve_pt(ncurrent_curve_polyline);
8769 for (
unsigned it = 0; it < ncurrent_curve_polyline; it++)
8771 current_curve_pt[it]->reverse();
8772 tmp_curve_pt[it] = current_curve_pt[it];
8776 for (
int i = ncurrent_curve_polyline - 1;
i >= 0;
i--,count++)
8777 {current_curve_pt[count] = tmp_curve_pt[
i];}
8779 list_building_polygon_pt.push_back(current_curve_pt);
8781 done_curve[ic] =
true;
8783 root_curve_final_vertex[0] = current_curve_initial_vertex[0];
8784 root_curve_final_vertex[1] = current_curve_initial_vertex[1];
8798 ((root_curve_initial_vertex[0] - root_curve_final_vertex[0])*
8799 (root_curve_initial_vertex[0] - root_curve_final_vertex[0]))
8801 ((root_curve_initial_vertex[1] - root_curve_final_vertex[1])*
8802 (root_curve_initial_vertex[1] - root_curve_final_vertex[1]));
8808 added_curve =
false;
8811 polygon_created =
true;
8817 }
while(added_curve);
8820 if (!polygon_created)
8822 std::stringstream error_message;
8824 <<
"It was no possible to create a TriangleMeshPolygon with "
8825 <<
"the input set of curves\n"
8826 <<
"These are the initial and final vertices in the current "
8827 <<
"sorted list of\nTriangleMeshPolyLines\n\n";
8830 unsigned icurve = 0;
8832 = list_building_polygon_pt.begin();
8833 it != list_building_polygon_pt.end(); it++, icurve++)
8835 const unsigned ncurrent_curve_polyline = (*it).size();
8837 <<
"TriangleMeshCurve #" << icurve <<
"\n"
8838 <<
"-----------------------------------\n";
8839 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++)
8843 (*it)[ip]->initial_vertex_coordinate(init_vertex);
8844 (*it)[ip]->final_vertex_coordinate(final_vertex);
8846 <<
"TriangleMeshPolyLine #" << ip <<
"\n"
8847 <<
"Initial vertex: ("<<init_vertex[0]<<
","<<init_vertex[1]<<
")\n"
8848 <<
"Final vertex: ("<<final_vertex[0]<<
","<<final_vertex[1]<<
")\n";
8853 "TriangleMesh::create_tmp_polygons_helper()",
8854 OOMPH_EXCEPTION_LOCATION);
8860 unsigned ntotal_polylines = 0;
8863 = list_building_polygon_pt.begin();
8864 it != list_building_polygon_pt.end(); it++)
8866 ntotal_polylines+=(*it).size();
8873 unsigned counter = 0;
8875 = list_building_polygon_pt.begin();
8876 it != list_building_polygon_pt.end(); it++)
8878 const unsigned ncurrent_curve_polyline = (*it).size();
8879 for (
unsigned ip = 0; ip < ncurrent_curve_polyline; ip++,counter++)
8881 curve_section_pt[counter] = (*it)[ip];
8890 this->Free_polygon_pt.insert(new_polygon_pt);
8893 polygons_pt.push_back(new_polygon_pt);
8898 }
while(nsorted_curves < nunsorted_curves);
8907 template<
class ELEMENT>
8915 const unsigned ninternal_open_curves = sorted_open_curves_pt.size();
8919 for (
unsigned i = 0;
i < ninternal_open_curves;
i++)
8922 const unsigned npoly = sorted_open_curves_pt[
i].size();
8924 for (
unsigned j = 0; j < npoly; j++)
8926 tmp_curve_section[j] = sorted_open_curves_pt[
i][j];
8933 this->Free_open_curve_pt.insert(new_open_curve_pt);
8936 open_curves_pt.push_back(new_open_curve_pt);
8948 template<
class ELEMENT>
8950 std::set<FiniteElement*> &element_in_processor_pt,
8951 const int &root_edge_bnd_id,
8952 std::map<std::pair<Node*,Node*>,
bool> &overlapped_face,
8953 std::map<
unsigned, std::map<Node*, bool> >
8954 &node_on_bnd_not_overlapped_by_shd_bnd,
8955 std::list<Node*> ¤t_polyline_nodes,
8956 std::map<
unsigned, std::list<Node*> >
8957 &shared_bnd_id_to_sorted_list_node_pt,
8958 const unsigned &node_degree,
8960 const bool called_from_load_balance)
8963 int flag_to_return = -1;
8972 bool overlapping_internal_boundary =
false;
8974 unsigned internal_overlaping_bnd_id = 0;
8975 if (root_edge_bnd_id != -1)
8978 overlapping_internal_boundary =
true;
8980 internal_overlaping_bnd_id =
static_cast<unsigned>(root_edge_bnd_id);
8991 bool is_node_living_in_non_overlapped_boundary =
false;
8995 const unsigned noriginal_bnd = this->initial_shared_boundary_id();
8996 for (
unsigned bb=0;bb<noriginal_bnd;bb++)
9004 if (overlapping_internal_boundary)
9013 const bool on_bnd_edge_not_overlapped_by_shd_bnd =
9014 node_on_bnd_not_overlapped_by_shd_bnd[bb][new_node_pt];
9015 if (bb != internal_overlaping_bnd_id ||
9016 ((bb == internal_overlaping_bnd_id) &&
9017 (on_bnd_edge_not_overlapped_by_shd_bnd)))
9020 if (bb != internal_overlaping_bnd_id)
9022 is_node_living_in_non_overlapped_boundary =
true;
9032 const unsigned n_bound_ele = this->nboundary_element(bb);
9033 if (n_bound_ele > 0)
9037 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9043 std::set<FiniteElement*>::iterator it =
9044 element_in_processor_pt.find(bulk_ele_pt);
9046 if (it!=element_in_processor_pt.end())
9049 bool found_node =
false;
9051 int face_index = this->face_index_at_boundary(bb,
e);
9056 const unsigned n_node_face = face_ele_pt->
nnode();
9059 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face-1);
9061 std::pair<Node*, Node*> tmp_edge =
9062 std::make_pair(first_node_pt, last_node_pt);
9066 if (!overlapped_face[tmp_edge])
9069 for (
unsigned n = 0;
n < n_node_face;
n++)
9072 if (face_ele_pt->
node_pt(
n) == new_node_pt)
9088 flag_to_return = bb;
9089 return flag_to_return;
9117 const unsigned n_bound_ele = this->nboundary_element(bb);
9118 if (n_bound_ele > 0)
9122 for (
unsigned e = 0;
e < n_bound_ele;
e++)
9128 std::set<FiniteElement*>::iterator it =
9129 element_in_processor_pt.find(bulk_ele_pt);
9131 if (it!=element_in_processor_pt.end())
9134 bool found_node =
false;
9136 int face_index = this->face_index_at_boundary(bb,
e);
9141 const unsigned n_node_face = face_ele_pt->
nnode();
9144 Node* last_node_pt = face_ele_pt->
node_pt(n_node_face-1);
9146 std::pair<Node*, Node*> tmp_edge =
9147 std::make_pair(first_node_pt, last_node_pt);
9151 if (!overlapped_face[tmp_edge])
9154 for (
unsigned n = 0;
n < n_node_face;
n++)
9157 if (face_ele_pt->
node_pt(
n) == new_node_pt)
9173 flag_to_return = bb;
9174 return flag_to_return;
9199 if (!overlapping_internal_boundary)
9204 flag_to_return = -3;
9211 if (is_node_living_in_non_overlapped_boundary)
9213 flag_to_return = -3;
9222 if (flag_to_return >= 0)
9224 return flag_to_return;
9237 for (std::map<
unsigned, std::list<Node*> >::iterator it =
9238 shared_bnd_id_to_sorted_list_node_pt.begin();
9239 it != shared_bnd_id_to_sorted_list_node_pt.end();
9245 const unsigned i_bnd_id = (*it).first;
9248 std::list<Node*>::iterator it_list = (*it).second.begin();
9250 const unsigned n_nodes = (*it).second.size();
9252 for (
unsigned i = 0;
i < n_nodes;
i++, it_list++)
9255 if ((*it_list) == new_node_pt)
9259 candidate_shared_bnd_to_connect.push_back(i_bnd_id);
9270 const unsigned n_candidate_shared_bnd_to_connect =
9271 candidate_shared_bnd_to_connect.size();
9274 if (n_candidate_shared_bnd_to_connect > 0)
9281 if (called_from_load_balance)
9283 return candidate_shared_bnd_to_connect[0];
9296 shared_boundaries_in_this_processor(shared_bound_in_this_proc);
9302 const unsigned n_shared_bound_in_this_proc =
9303 shared_bound_in_this_proc.size();
9306 for (
unsigned i = 0;
i < n_candidate_shared_bnd_to_connect;
i++)
9309 const unsigned i_candidate_shared_bnd =
9310 candidate_shared_bnd_to_connect[
i];
9313 for (
unsigned j = 0; j < n_shared_bound_in_this_proc; j++)
9316 if (i_candidate_shared_bnd == shared_bound_in_this_proc[j])
9319 flag_to_return = i_candidate_shared_bnd;
9320 return flag_to_return;
9331 flag_to_return = -3;
9337 if (flag_to_return >= 0)
9339 return flag_to_return;
9348 unsigned nrepeated = 0;
9349 for (std::list<Node*>::iterator it_list = current_polyline_nodes.begin();
9350 it_list != current_polyline_nodes.end();
9355 if ((*it_list) == new_node_pt) {nrepeated++;}
9364 flag_to_return = -2;
9370 if (node_degree > 2)
9372 flag_to_return = -3;
9376 return flag_to_return;
9387 template<
class ELEMENT>
9391 const unsigned my_rank = this->communicator_pt()->my_rank();
9395 this->Shared_boundary_polyline_pt[my_rank];
9399 const unsigned ncurves = shared_curves_pt.size();
9400 for (
unsigned icurve = 0; icurve < ncurves; icurve++)
9403 const unsigned npoly = shared_curves_pt[icurve].size();
9404 for (
unsigned ipoly = 0; ipoly < npoly; ipoly++)
9410 const unsigned bound_id = shd_poly_pt->
boundary_id();
9413 const bool is_connected_to_the_left =
9417 const bool is_connected_to_the_right =
9423 if (is_connected_to_the_left || is_connected_to_the_right)
9427 const unsigned n_vertex = shd_poly_pt->
nvertex();
9434 if (is_connected_to_the_left)
9438 const unsigned uconnection_to_the_left =
9446 bool connecting_to_an_split_boundary =
false;
9450 bool connecting_to_an_overlaped_boundary =
false;
9453 if (uconnection_to_the_left == bound_id)
9456 poly_to_connect_pt = shd_poly_pt;
9461 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
9463 if (uconnection_to_the_left >= initial_shd_bnd_id)
9467 poly_to_connect_pt =
9468 boundary_polyline_pt(uconnection_to_the_left);
9476 if (boundary_was_splitted(uconnection_to_the_left))
9478 connecting_to_an_split_boundary =
true;
9488 if (connecting_to_an_split_boundary)
9492 const unsigned n_sub_poly =
9493 nboundary_subpolylines(uconnection_to_the_left);
9498 for (
unsigned ii =0; ii < n_sub_poly; ii++)
9500 if (boundary_marked_as_shared_boundary(
9501 uconnection_to_the_left, ii))
9505 connecting_to_an_overlaped_boundary =
true;
9516 if (boundary_marked_as_shared_boundary(
9517 uconnection_to_the_left, 0))
9521 connecting_to_an_overlaped_boundary =
true;
9528 if (!(connecting_to_an_split_boundary ||
9529 connecting_to_an_overlaped_boundary))
9533 poly_to_connect_pt =
9534 boundary_polyline_pt(uconnection_to_the_left);
9545 if (!connecting_to_an_split_boundary)
9547 if (boundary_was_splitted(uconnection_to_the_left))
9549 std::stringstream error;
9551 <<
"The current shared boundary (" << bound_id <<
") was "
9552 <<
"marked to have a connection\nto the left with the "
9553 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9554 <<
"The problem is that the destination boundary (possibly\n"
9555 <<
"another shared boundary) is marked to be split\n"
9556 <<
"There should not be split shared boundaries\n\n";
9559 "TriangleMesh::create_shared_polylines_connections()",
9560 OOMPH_EXCEPTION_LOCATION);
9577 if (!connecting_to_an_split_boundary)
9581 if (!connecting_to_an_overlaped_boundary)
9585 unsigned vertex_index = 0;
9587 const bool found_vertex_index =
9588 get_connected_vertex_number_on_destination_polyline(
9589 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9593 if (!found_vertex_index)
9595 std::stringstream error;
9597 <<
"The current shared boundary (" << bound_id <<
") was "
9598 <<
"marked to have a connection\nto the left with the "
9599 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9600 <<
"The problem is that the left vertex of the current\n"
9601 <<
"shared boundary is not in the list of vertices of the\n"
9602 <<
"boundary to connect.\n\n"
9603 <<
"This is the left vertex of the current shared boundary\n"
9604 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9605 << shd_bnd_left_vertex[1] <<
")\n\n"
9606 <<
"This is the list of vertices on the destination "
9608 const unsigned n_v = poly_to_connect_pt->
nvertex();
9609 for (
unsigned i = 0;
i < n_v;
i++)
9614 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
9618 "TriangleMesh::create_shared_polylines_connections()",
9619 OOMPH_EXCEPTION_LOCATION);
9626 poly_to_connect_pt, vertex_index);
9636 unsigned vertex_index = 0;
9638 bool found_vertex_index =
false;
9643 get_shared_boundaries_overlapping_internal_boundary(
9644 uconnection_to_the_left, dst_shd_bnd_ids);
9648 const unsigned n_shd_bnd_overlap_int_bnd =
9649 dst_shd_bnd_ids.size();
9653 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9656 const unsigned new_connection_to_the_left =
9657 dst_shd_bnd_ids[ss];
9661 poly_to_connect_pt =
9662 boundary_polyline_pt(new_connection_to_the_left);
9664 if (poly_to_connect_pt!=0)
9668 found_vertex_index =
9669 get_connected_vertex_number_on_destination_polyline(
9670 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9675 if (found_vertex_index)
9685 if (!found_vertex_index)
9687 std::stringstream error;
9689 <<
"The current shared boundary (" << bound_id <<
") was "
9690 <<
"marked to have a connection\nto the left with the "
9691 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9692 <<
"This last boundary is marked to be overlaped by "
9693 <<
"shared boundaries\n"
9694 <<
"The problem is that the left vertex of the current\n"
9695 <<
"shared boundary is not in the list of vertices of the\n"
9696 <<
"boundary to connect.\n\n"
9697 <<
"This is the left vertex of the current shared boundary\n"
9698 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9699 << shd_bnd_left_vertex[1] <<
")\n\n"
9700 <<
"This is the list of vertices on the destination "
9703 get_shared_boundaries_overlapping_internal_boundary(
9704 uconnection_to_the_left, dst_shd_bnd_ids);
9705 const unsigned n_shd_bnd_overlap_int_bnd =
9706 dst_shd_bnd_ids.size();
9707 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9709 const unsigned new_connection_to_the_left =
9710 dst_shd_bnd_ids[ss];
9711 poly_to_connect_pt =
9712 boundary_polyline_pt(new_connection_to_the_left);
9713 if (poly_to_connect_pt != 0)
9715 const unsigned shd_bnd_id_overlap =
9717 error <<
"Shared boundary id("
9718 << shd_bnd_id_overlap <<
")\n";
9719 const unsigned n_v = poly_to_connect_pt->
nvertex();
9720 for (
unsigned i = 0;
i < n_v;
i++)
9725 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
9726 <<cvertex[1]<<
")\n";
9733 "TriangleMesh::create_shared_polylines_connections()",
9734 OOMPH_EXCEPTION_LOCATION);
9743 poly_to_connect_pt, vertex_index);
9755 boundary_subpolylines(uconnection_to_the_left);
9758 const unsigned nsub_poly = tmp_vector_subpolylines.size();
9762 std::ostringstream error_message;
9764 <<
"The boundary (" << uconnection_to_the_left <<
") was "
9765 <<
"marked to be splitted but\n"
9766 <<
"there are only ("<<nsub_poly<<
") polylines to "
9767 <<
"represent it.\n";
9769 error_message.str(),
9770 "TriangleMesh::create_shared_polylines_connections()",
9771 OOMPH_EXCEPTION_LOCATION);
9783 if (!connecting_to_an_overlaped_boundary)
9789 unsigned vertex_index = 0;
9791 unsigned sub_poly_to_connect = 0;
9793 bool found_vertex_index =
false;
9797 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9800 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9802 found_vertex_index =
9803 get_connected_vertex_number_on_destination_polyline(
9804 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9807 if (found_vertex_index)
9811 sub_poly_to_connect = isub;
9819 if (!found_vertex_index)
9821 std::stringstream error;
9823 <<
"The current shared boundary (" << bound_id <<
") was "
9824 <<
"marked to have a connection\nto the left with the "
9825 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9826 <<
"The problem is that the left vertex of the current\n"
9827 <<
"shared boundary is not in the list of vertices of any\n"
9828 <<
"of the sub polylines that represent the boundary to\n"
9830 <<
"This is the left vertex of the current shared boundary\n"
9831 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9832 << shd_bnd_left_vertex[1] <<
")\n\n"
9833 <<
"This is the list of vertices on the destination "
9835 for (
unsigned p = 0; p < nsub_poly; p++)
9837 error <<
"Subpolyline #("<< p <<
")\n";
9838 poly_to_connect_pt = tmp_vector_subpolylines[p];
9839 const unsigned n_v = poly_to_connect_pt->
nvertex();
9840 for (
unsigned i = 0;
i < n_v;
i++)
9845 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
9846 <<cvertex[1]<<
")\n";
9851 "TriangleMesh::create_shared_polylines_connections()",
9852 OOMPH_EXCEPTION_LOCATION);
9861 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
9872 unsigned vertex_index = 0;
9874 unsigned sub_poly_to_connect = 0;
9876 bool found_vertex_index =
false;
9881 get_shared_boundaries_overlapping_internal_boundary(
9882 uconnection_to_the_left, dst_shd_bnd_ids);
9886 const unsigned n_shd_bnd_overlap_int_bnd =
9887 dst_shd_bnd_ids.size();
9891 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
9894 const unsigned new_connection_to_the_left =
9895 dst_shd_bnd_ids[ss];
9899 if (bound_id != new_connection_to_the_left)
9903 poly_to_connect_pt =
9904 boundary_polyline_pt(new_connection_to_the_left);
9906 if (poly_to_connect_pt != 0)
9910 found_vertex_index =
9911 get_connected_vertex_number_on_destination_polyline(
9912 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9917 if (found_vertex_index)
9929 if (!found_vertex_index)
9933 for (
unsigned isub = 0; isub < nsub_poly; isub++)
9937 if (!boundary_marked_as_shared_boundary(
9938 uconnection_to_the_left, isub))
9941 poly_to_connect_pt = tmp_vector_subpolylines[isub];
9943 found_vertex_index =
9944 get_connected_vertex_number_on_destination_polyline(
9945 poly_to_connect_pt, shd_bnd_left_vertex, vertex_index);
9948 if (found_vertex_index)
9952 sub_poly_to_connect = isub;
9965 if (!found_vertex_index)
9967 std::stringstream error;
9969 <<
"The current shared boundary (" << bound_id <<
") was "
9970 <<
"marked to have a connection\nto the left with the "
9971 <<
"boundary (" << uconnection_to_the_left <<
").\n"
9972 <<
"This last boundary is marked to be overlaped by "
9973 <<
"shared boundaries\n"
9974 <<
"The problem is that the left vertex of the current\n"
9975 <<
"shared boundary is not in the list of vertices of "
9976 <<
"the\nboundary to connect.\n\n"
9977 <<
"This is the left vertex of the current shared "
9979 <<
"Left vertex: (" << shd_bnd_left_vertex[0] <<
", "
9980 << shd_bnd_left_vertex[1] <<
")\n\n"
9981 <<
"This is the list of vertices on the destination "
9982 <<
"boundary (only those subpolylines not marked as "
9983 <<
"overlaped by\nshared boundaries)\n";
9984 for (
unsigned p = 0; p < nsub_poly; p++)
9986 if (!boundary_marked_as_shared_boundary(
9987 uconnection_to_the_left, p))
9989 error <<
"Subpolyline #("<< p <<
")\n";
9990 poly_to_connect_pt = tmp_vector_subpolylines[p];
9991 const unsigned n_v = poly_to_connect_pt->
nvertex();
9992 for (
unsigned i = 0;
i < n_v;
i++)
9997 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
9998 <<cvertex[1]<<
")\n";
10002 error <<
"\nThis is the list of vertices of the shared "
10003 <<
"polylines that overlap\nthe internal "
10006 get_shared_boundaries_overlapping_internal_boundary(
10007 uconnection_to_the_left, dst_shd_bnd_ids);
10008 const unsigned n_shd_bnd_overlap_int_bnd =
10009 dst_shd_bnd_ids.size();
10010 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10012 const unsigned new_connection_to_the_left =
10013 dst_shd_bnd_ids[ss];
10014 poly_to_connect_pt =
10015 boundary_polyline_pt(new_connection_to_the_left);
10016 if (poly_to_connect_pt != 0)
10018 const unsigned shd_bnd_id_overlap =
10020 error <<
"Shared boundary id("
10021 << shd_bnd_id_overlap <<
")\n";
10022 const unsigned n_v = poly_to_connect_pt->
nvertex();
10023 for (
unsigned i = 0;
i < n_v;
i++)
10028 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
10029 <<cvertex[1]<<
")\n";
10036 "TriangleMesh::create_shared_polylines_connections()",
10037 OOMPH_EXCEPTION_LOCATION);
10046 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10056 if (is_connected_to_the_right)
10060 const unsigned uconnection_to_the_right =
10068 bool connecting_to_an_split_boundary =
false;
10072 bool connecting_to_an_overlaped_boundary =
false;
10075 if (uconnection_to_the_right == bound_id)
10078 poly_to_connect_pt = shd_poly_pt;
10083 const unsigned initial_shd_bnd_id = initial_shared_boundary_id();
10085 if (uconnection_to_the_right >= initial_shd_bnd_id)
10089 poly_to_connect_pt =
10090 boundary_polyline_pt(uconnection_to_the_right);
10098 if (boundary_was_splitted(uconnection_to_the_right))
10100 connecting_to_an_split_boundary =
true;
10110 if (connecting_to_an_split_boundary)
10114 const unsigned n_sub_poly =
10115 nboundary_subpolylines(uconnection_to_the_right);
10120 for (
unsigned ii =0; ii < n_sub_poly; ii++)
10122 if (boundary_marked_as_shared_boundary(
10123 uconnection_to_the_right, ii))
10127 connecting_to_an_overlaped_boundary =
true;
10138 if (boundary_marked_as_shared_boundary(
10139 uconnection_to_the_right, 0))
10143 connecting_to_an_overlaped_boundary =
true;
10150 if (!(connecting_to_an_split_boundary ||
10151 connecting_to_an_overlaped_boundary))
10155 poly_to_connect_pt =
10156 boundary_polyline_pt(uconnection_to_the_right);
10167 if (!connecting_to_an_split_boundary)
10169 if (boundary_was_splitted(uconnection_to_the_right))
10171 std::stringstream error;
10173 <<
"The current shared boundary (" << bound_id <<
") was "
10174 <<
"marked to have a connection\nto the right with the "
10175 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10176 <<
"The problem is that the destination boundary (possibly\n"
10177 <<
"another shared boundary) is marked to be split\n"
10178 <<
"There should not be split shared boundaries\n\n";
10181 "TriangleMesh::create_shared_polylines_connections()",
10182 OOMPH_EXCEPTION_LOCATION);
10200 if (!connecting_to_an_split_boundary)
10204 if (!connecting_to_an_overlaped_boundary)
10209 unsigned vertex_index = 0;
10210 const bool found_vertex_index =
10211 get_connected_vertex_number_on_destination_polyline(
10212 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10216 if (!found_vertex_index)
10218 std::stringstream error;
10220 <<
"The current shared boundary (" << bound_id <<
") was "
10221 <<
"marked to have a connection\nto the right with the "
10222 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10223 <<
"The problem is that the right vertex of the current\n"
10224 <<
"shared boundary is not in the list of vertices of the\n"
10225 <<
"boundary to connect.\n\n"
10226 <<
"This is the right vertex of the current shared boundary\n"
10227 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10228 << shd_bnd_right_vertex[1] <<
")\n\n"
10229 <<
"This is the list of vertices on the destination boundary\n";
10230 const unsigned n_v = poly_to_connect_pt->
nvertex();
10231 for (
unsigned i = 0;
i < n_v;
i++)
10236 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "<<cvertex[1]<<
")\n";
10240 "TriangleMesh::create_shared_polylines_connections()",
10241 OOMPH_EXCEPTION_LOCATION);
10248 poly_to_connect_pt, vertex_index);
10258 unsigned vertex_index = 0;
10260 bool found_vertex_index =
false;
10265 get_shared_boundaries_overlapping_internal_boundary(
10266 uconnection_to_the_right, dst_shd_bnd_ids);
10270 const unsigned n_shd_bnd_overlap_int_bnd =
10271 dst_shd_bnd_ids.size();
10275 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10278 const unsigned new_connection_to_the_right =
10279 dst_shd_bnd_ids[ss];
10283 poly_to_connect_pt =
10284 boundary_polyline_pt(new_connection_to_the_right);
10286 if (poly_to_connect_pt!=0)
10290 found_vertex_index =
10291 get_connected_vertex_number_on_destination_polyline(
10292 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10297 if (found_vertex_index)
10307 if (!found_vertex_index)
10309 std::stringstream error;
10311 <<
"The current shared boundary (" << bound_id <<
") was "
10312 <<
"marked to have a connection\nto the right with the "
10313 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10314 <<
"This last boundary is marked to be overlaped by "
10315 <<
"shared boundaries\n"
10316 <<
"The problem is that the right vertex of the current\n"
10317 <<
"shared boundary is not in the list of vertices of the\n"
10318 <<
"boundary to connect.\n\n"
10319 <<
"This is the right vertex of the current shared boundary\n"
10320 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10321 << shd_bnd_right_vertex[1] <<
")\n\n"
10322 <<
"This is the list of vertices on the destination "
10325 get_shared_boundaries_overlapping_internal_boundary(
10326 uconnection_to_the_right, dst_shd_bnd_ids);
10327 const unsigned n_shd_bnd_overlap_int_bnd =
10328 dst_shd_bnd_ids.size();
10329 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10331 const unsigned new_connection_to_the_right =
10332 dst_shd_bnd_ids[ss];
10333 poly_to_connect_pt =
10334 boundary_polyline_pt(new_connection_to_the_right);
10335 if (poly_to_connect_pt != 0)
10337 const unsigned shd_bnd_id_overlap =
10339 error <<
"Shared boundary id("
10340 << shd_bnd_id_overlap <<
")\n";
10341 const unsigned n_v = poly_to_connect_pt->
nvertex();
10342 for (
unsigned i = 0;
i < n_v;
i++)
10347 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
10348 <<cvertex[1]<<
")\n";
10355 "TriangleMesh::create_shared_polylines_connections()",
10356 OOMPH_EXCEPTION_LOCATION);
10365 poly_to_connect_pt, vertex_index);
10377 boundary_subpolylines(uconnection_to_the_right);
10380 const unsigned nsub_poly = tmp_vector_subpolylines.size();
10382 if (nsub_poly <= 1)
10384 std::ostringstream error_message;
10386 <<
"The boundary (" << uconnection_to_the_right <<
") was "
10387 <<
"marked to be splitted but\n"
10388 <<
"there are only ("<<nsub_poly<<
") polylines to "
10389 <<
"represent it.\n";
10391 error_message.str(),
10392 "TriangleMesh::create_shared_polylines_connections()",
10393 OOMPH_EXCEPTION_LOCATION);
10406 if (!connecting_to_an_overlaped_boundary)
10412 unsigned vertex_index = 0;
10414 unsigned sub_poly_to_connect = 0;
10416 bool found_vertex_index =
false;
10420 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10423 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10425 found_vertex_index =
10426 get_connected_vertex_number_on_destination_polyline(
10427 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10430 if (found_vertex_index)
10434 sub_poly_to_connect = isub;
10442 if (!found_vertex_index)
10444 std::stringstream error;
10446 <<
"The current shared boundary (" << bound_id <<
") was "
10447 <<
"marked to have a connection\nto the right with the "
10448 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10449 <<
"The problem is that the right vertex of the current\n"
10450 <<
"shared boundary is not in the list of vertices of any\n"
10451 <<
"of the sub polylines that represent the boundary to\n"
10453 <<
"This is the right vertex of the current shared boundary\n"
10454 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10455 << shd_bnd_right_vertex[1] <<
")\n\n"
10456 <<
"This is the list of vertices on the destination "
10458 for (
unsigned p = 0; p < nsub_poly; p++)
10460 error <<
"Subpolyline #("<< p <<
")\n";
10461 poly_to_connect_pt = tmp_vector_subpolylines[p];
10462 const unsigned n_v = poly_to_connect_pt->
nvertex();
10463 for (
unsigned i = 0;
i < n_v;
i++)
10468 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]
10469 <<
", "<<cvertex[1]<<
")\n";
10474 "TriangleMesh::create_shared_polylines_connections()",
10475 OOMPH_EXCEPTION_LOCATION);
10484 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10495 unsigned vertex_index = 0;
10497 unsigned sub_poly_to_connect = 0;
10499 bool found_vertex_index =
false;
10504 get_shared_boundaries_overlapping_internal_boundary(
10505 uconnection_to_the_right, dst_shd_bnd_ids);
10509 const unsigned n_shd_bnd_overlap_int_bnd =
10510 dst_shd_bnd_ids.size();
10514 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10517 const unsigned new_connection_to_the_right =
10518 dst_shd_bnd_ids[ss];
10522 if (bound_id != new_connection_to_the_right)
10526 poly_to_connect_pt =
10527 boundary_polyline_pt(new_connection_to_the_right);
10529 if (poly_to_connect_pt != 0)
10533 found_vertex_index =
10534 get_connected_vertex_number_on_destination_polyline(
10535 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10540 if (found_vertex_index)
10552 if (!found_vertex_index)
10556 for (
unsigned isub = 0; isub < nsub_poly; isub++)
10560 if (!boundary_marked_as_shared_boundary(
10561 uconnection_to_the_right, isub))
10564 poly_to_connect_pt = tmp_vector_subpolylines[isub];
10566 found_vertex_index =
10567 get_connected_vertex_number_on_destination_polyline(
10568 poly_to_connect_pt, shd_bnd_right_vertex, vertex_index);
10571 if (found_vertex_index)
10575 sub_poly_to_connect = isub;
10588 if (!found_vertex_index)
10590 std::stringstream error;
10592 <<
"The current shared boundary (" << bound_id <<
") was "
10593 <<
"marked to have a connection\nto the right with the "
10594 <<
"boundary (" << uconnection_to_the_right <<
").\n"
10595 <<
"This last boundary is marked to be overlaped by "
10596 <<
"shared boundaries\n"
10597 <<
"The problem is that the right vertex of the current\n"
10598 <<
"shared boundary is not in the list of vertices of "
10599 <<
"the\nboundary to connect.\n\n"
10600 <<
"This is the right vertex of the current shared "
10602 <<
"Right vertex: (" << shd_bnd_right_vertex[0] <<
", "
10603 << shd_bnd_right_vertex[1] <<
")\n\n"
10604 <<
"This is the list of vertices on the destination "
10605 <<
"boundary (only those subpolylines not marked as "
10606 <<
"overlaped by\nshared boundaries)\n";
10607 for (
unsigned p = 0; p < nsub_poly; p++)
10609 if (!boundary_marked_as_shared_boundary(
10610 uconnection_to_the_right, p))
10612 error <<
"Subpolyline #("<< p <<
")\n";
10613 poly_to_connect_pt = tmp_vector_subpolylines[p];
10614 const unsigned n_v = poly_to_connect_pt->
nvertex();
10615 for (
unsigned i = 0;
i < n_v;
i++)
10620 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
10621 <<cvertex[1]<<
")\n";
10625 error <<
"\nThis is the list of vertices of the shared "
10626 <<
"polylines that overlap\nthe internal "
10629 get_shared_boundaries_overlapping_internal_boundary(
10630 uconnection_to_the_right, dst_shd_bnd_ids);
10631 const unsigned n_shd_bnd_overlap_int_bnd =
10632 dst_shd_bnd_ids.size();
10633 for (
unsigned ss = 0; ss < n_shd_bnd_overlap_int_bnd; ss++)
10635 const unsigned new_connection_to_the_right =
10636 dst_shd_bnd_ids[ss];
10637 poly_to_connect_pt =
10638 boundary_polyline_pt(new_connection_to_the_right);
10639 if (poly_to_connect_pt != 0)
10641 const unsigned shd_bnd_id_overlap =
10643 error <<
"Shared boundary id("
10644 << shd_bnd_id_overlap <<
")\n";
10645 const unsigned n_v = poly_to_connect_pt->
nvertex();
10646 for (
unsigned i = 0;
i < n_v;
i++)
10651 <<
"Vertex #"<<
i<<
": ("<<cvertex[0]<<
", "
10652 <<cvertex[1]<<
")\n";
10659 "TriangleMesh::create_shared_polylines_connections()",
10660 OOMPH_EXCEPTION_LOCATION);
10669 poly_to_connect_pt, vertex_index, sub_poly_to_connect);
10689 template<
class ELEMENT>
10694 const unsigned n_proc = this->communicator_pt()->nproc();
10695 const unsigned my_rank = this->communicator_pt()->my_rank();
10699 std::map<FiniteElement*, bool> done_ele;
10703 for (
unsigned iproc = 0; iproc < n_proc; iproc++)
10706 if (iproc != my_rank)
10709 const unsigned n_shd_bnd_iproc = nshared_boundaries(my_rank, iproc);
10714 const unsigned n_shd_bnd_iproc_rev = nshared_boundaries(iproc, my_rank);
10715 if (n_shd_bnd_iproc != n_shd_bnd_iproc_rev)
10717 std::ostringstream error_stream;
10719 <<
"The number of shared boundaries of processor ("
10720 << my_rank <<
") with processor(" << iproc <<
"): ("
10721 << n_shd_bnd_iproc <<
")\n"
10722 <<
"is different from the number of shared boundaries of "
10723 <<
"processor (" << iproc <<
")\nwith processor ("
10724 << my_rank <<
"): (" << n_shd_bnd_iproc <<
")\n\n";
10726 OOMPH_CURRENT_FUNCTION,
10727 OOMPH_EXCEPTION_LOCATION);
10733 for (
unsigned i = 0;
i < n_shd_bnd_iproc;
i++)
10736 const unsigned shd_bnd_id = shared_boundaries_ids(my_rank, iproc,
i);
10739 const unsigned n_shd_bnd_ele = nshared_boundary_element(shd_bnd_id);
10742 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
10745 FiniteElement* ele_pt = shared_boundary_element_pt(shd_bnd_id,
e);
10751 if (!done_ele[ele_pt])
10754 const unsigned n_nodes = ele_pt->nnode();
10759 for (
unsigned k = 0; k < n_nodes; k++)
10761 Node* tmp_node_pt = ele_pt->node_pt(k);
10763 for (
unsigned d = 0; d < 2; d++)
10765 element_centroid[d]+=tmp_node_pt->
x(d);
10770 for (
unsigned d = 0; d < 2; d++)
10772 element_centroid[d] =
10773 element_centroid[d] / (double)n_nodes;
10777 output_holes_coordinates.push_back(element_centroid);
10800 template<
class ELEMENT>
10821 const unsigned n_input_holes = output_holes_coordinates.size();
10824 if (n_input_holes == 0)
10830 const unsigned n_polygons = polygons_pt.size();
10839 for (
unsigned p = 0; p < n_polygons; p++)
10842 const unsigned n_polylines = polygons_pt[p]->npolyline();
10844 for (
unsigned pp = 0; pp < n_polylines; pp++)
10848 polygons_pt[p]->polyline_pt(pp);
10850 const unsigned n_vertices = tmp_poly_pt->
nvertex();
10854 for (
unsigned v = 0; v < n_vertices-1; v++)
10858 vertices_polygons[p].push_back(current_vertex);
10870 std::vector<bool> is_outer_polygon(n_polygons,
true);
10874 if (n_polygons > 1)
10883 for (
unsigned p = 0; p < n_polygons; p++)
10889 const unsigned n_vertices = tmp_inner_polygon.size();
10892 polygon_edge_middle_vertex[p].resize(n_vertices-1);
10896 for (
unsigned e = 0;
e < n_vertices - 1;
e++)
10899 const unsigned dim = 2;
10900 polygon_edge_middle_vertex[p][
e].resize(dim);
10901 for (
unsigned d = 0; d < dim; d++)
10903 polygon_edge_middle_vertex[p][
e][d] =
10904 (tmp_inner_polygon[
e][d] + tmp_inner_polygon[
e+1][d]) / 2.0;
10913 for (
unsigned idx_inner = 0; idx_inner < n_polygons; idx_inner++)
10918 bool is_inner_polygon =
false;
10923 for (
unsigned i = 0;
i < n_polygons;
i++)
10926 if (
i != idx_inner)
10929 const unsigned n_edges =
10930 polygon_edge_middle_vertex[idx_inner].size();
10933 for (
unsigned e = 0;
e < n_edges;
e++)
10937 polygon_edge_middle_vertex[idx_inner][
e];
10940 const bool is_point_inside =
10941 is_point_inside_polygon_helper(vertices_polygons[
i],
10946 if (is_point_inside)
10949 is_inner_polygon =
true;
10960 if (is_inner_polygon)
10970 if (is_inner_polygon)
10973 is_outer_polygon[idx_inner] =
false;
10979 is_outer_polygon[idx_inner] =
true;
10988 unsigned n_outer_polygons = 0;
10989 unsigned n_inner_polygons = 0;
10993 for (
unsigned i = 0;
i < n_polygons;
i++)
10995 if (is_outer_polygon[
i])
10998 n_outer_polygons++;
11003 n_inner_polygons++;
11005 index_inner_polygon.push_back(
i);
11024 std::vector<bool> is_inside_an_inner_polygon(n_input_holes,
false);
11028 std::vector<bool> is_outside_the_outer_polygons(n_input_holes,
true);
11032 std::vector<bool> is_inside_the_convex_hull(n_input_holes,
false);
11036 vertex_inside_inner_polygon(n_inner_polygons);
11041 for (
unsigned i = 0;
i < n_inner_polygons;
i++)
11044 const unsigned ii = index_inner_polygon[
i];
11047 for (
unsigned h = 0; h < n_input_holes; h++)
11051 if (!is_inside_an_inner_polygon[h])
11054 const bool is_inside_polygon =
11055 is_point_inside_polygon_helper(vertices_polygons[ii],
11056 output_holes_coordinates[h]);
11060 if (is_inside_polygon)
11063 is_inside_an_inner_polygon[h] =
true;
11065 vertex_inside_inner_polygon[
i].
11066 push_back(output_holes_coordinates[h]);
11078 for (
unsigned h = 0; h < n_input_holes; h++)
11082 if (!is_inside_an_inner_polygon[h])
11086 for (
unsigned i = 0;
i < n_polygons;
i++)
11089 if (is_outer_polygon[
i])
11092 const bool is_inside_polygon =
11093 is_point_inside_polygon_helper(vertices_polygons[
i],
11094 output_holes_coordinates[h]);
11099 if (is_inside_polygon)
11102 is_outside_the_outer_polygons[h] =
false;
11116 is_outside_the_outer_polygons[h] =
false;
11123 std::vector<Point> input_vertices_convex_hull;
11126 for (
unsigned p = 0; p < n_polygons; p++)
11129 const unsigned n_vertices = vertices_polygons[p].size();
11131 for (
unsigned v = 0; v < n_vertices; v++)
11136 point.
x = vertices_polygons[p][v][0];
11137 point.
y = vertices_polygons[p][v][1];
11139 input_vertices_convex_hull.push_back(point);
11144 std::vector<Point> output_vertices_convex_hull =
11145 convex_hull(input_vertices_convex_hull);
11148 const unsigned n_vertices_convex_hull = output_vertices_convex_hull.size();
11152 for (
unsigned i = 0;
i < n_vertices_convex_hull;
i++)
11155 vertices_convex_hull[
i].resize(2);
11157 vertices_convex_hull[
i][0] = output_vertices_convex_hull[
i].x;
11158 vertices_convex_hull[
i][1] = output_vertices_convex_hull[
i].y;
11164 for (
unsigned h = 0; h < n_input_holes; h++)
11167 if (is_outside_the_outer_polygons[h])
11170 const bool is_inside_convex_hull =
11171 is_point_inside_polygon_helper(vertices_convex_hull,
11172 output_holes_coordinates[h]);
11175 if (is_inside_convex_hull)
11178 is_inside_the_convex_hull[h] =
true;
11185 is_inside_the_convex_hull[h] =
true;
11193 for (
unsigned h = 0; h < n_input_holes; h++)
11196 if ((is_inside_an_inner_polygon[h]) ||
11197 (is_outside_the_outer_polygons[h] && is_inside_the_convex_hull[h]))
11200 hole_kept.push_back(output_holes_coordinates[h]);
11205 output_holes_coordinates.clear();
11207 output_holes_coordinates = hole_kept;
11215 template<
class ELEMENT>
11218 &unsorted_polylines_pt,
11220 &sorted_polylines_pt)
11222 unsigned n_unsorted_polylines = unsorted_polylines_pt.size();
11223 unsigned n_sorted_polylines = 0;
11224 unsigned curves_index = 0;
11227 std::map<TriangleMeshPolyLine*, bool> done_polyline;
11233 std::list<TriangleMeshPolyLine*> sorted_polyline_list_pt;
11234 bool changes =
false;
11243 bool found_root_polyline =
false;
11244 while (pp < n_unsorted_polylines && !found_root_polyline)
11246 if (!done_polyline[unsorted_polylines_pt[pp]])
11247 {found_root_polyline =
true;}
11253 if (pp < n_unsorted_polylines)
11256 left_pt = right_pt = unsorted_polylines_pt[pp];
11257 done_polyline[left_pt] =
true;
11259 n_sorted_polylines++;
11263 sorted_polyline_list_pt.push_back(left_pt);
11275 for (
unsigned i = pp+1;
i < n_unsorted_polylines;
i++)
11278 unsorted_polylines_pt[
i];
11279 if (!done_polyline[current_polyline_pt])
11283 current_polyline_pt->initial_vertex_coordinate(initial_vertex);
11284 current_polyline_pt->final_vertex_coordinate(final_vertex);
11290 if (left_vertex == final_vertex)
11292 left_pt = current_polyline_pt;
11293 sorted_polyline_list_pt.push_front(left_pt);
11294 done_polyline[left_pt] =
true;
11295 n_sorted_polylines++;
11301 else if (right_vertex == initial_vertex)
11303 right_pt = current_polyline_pt;
11304 sorted_polyline_list_pt.push_back(right_pt);
11305 done_polyline[right_pt] =
true;
11306 n_sorted_polylines++;
11312 else if (left_vertex == initial_vertex)
11314 current_polyline_pt->
reverse();
11315 left_pt = current_polyline_pt;
11316 sorted_polyline_list_pt.push_front(left_pt);
11317 done_polyline[left_pt] =
true;
11318 n_sorted_polylines++;
11324 else if (right_vertex == final_vertex)
11326 current_polyline_pt->
reverse();
11327 right_pt = current_polyline_pt;
11328 sorted_polyline_list_pt.push_back(right_pt);
11329 done_polyline[right_pt] =
true;
11330 n_sorted_polylines++;
11336 if (changes) {
break;}
11348 if (!found_root_polyline)
11350 std::stringstream err;
11351 err <<
"It was not possible to find a root polyline to sort the "
11352 <<
"others around it.\nThe number of unsorted and sorted "
11353 <<
"polylines is different, it means that\nnot all the "
11354 <<
"polylines have been sorted.\n"
11355 <<
"Found root polyline: ("<<found_root_polyline<<
")\n"
11356 <<
"Sorted polylines: ("<<n_sorted_polylines<<
")\n"
11357 <<
"Unsorted polylines: ("<<n_unsorted_polylines<<
")\n";
11358 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11359 OOMPH_EXCEPTION_LOCATION);
11366 unsigned n_sorted_polyline_on_list = sorted_polyline_list_pt.size();
11370 tmp_sorted_polylines(n_sorted_polyline_on_list);
11371 unsigned counter = 0;
11373 std::list<TriangleMeshPolyLine*>::iterator it_polyline;
11374 for (it_polyline = sorted_polyline_list_pt.begin();
11375 it_polyline != sorted_polyline_list_pt.end();
11378 tmp_sorted_polylines[counter] = *it_polyline;
11382 sorted_polylines_pt.push_back(tmp_sorted_polylines);
11386 }
while(n_sorted_polylines < n_unsorted_polylines);
11391 if (n_sorted_polylines != n_unsorted_polylines)
11393 std::stringstream err;
11394 err <<
"The number of polylines on the unsorted and sorted vectors"
11395 <<
" is different,\n"
11396 <<
"it means that not all the polylines have been sorted.\n"
11397 <<
"Sorted polylines: "<<n_sorted_polylines
11398 <<
"\nUnsorted polylines: "<<n_unsorted_polylines;
11399 throw OomphLibError(err.str(),
"TriangleMesh::sort_polylines_helper()",
11400 OOMPH_EXCEPTION_LOCATION);
11409 template<
class ELEMENT>
11415 std::map<
Data*,std::set<unsigned> > &processors_associated_with_data,
11416 const bool& overrule_keep_as_halo_element_status)
11419 const unsigned nproc = comm_pt->nproc();
11420 const unsigned my_rank = comm_pt->my_rank();
11428 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11429 {halo_element_pt[iproc].resize(nproc);}
11434 std::map<GeneralisedElement*, unsigned> element_to_global_index;
11437 this->get_halo_elements_on_all_procs(nproc, element_domain,
11439 processors_associated_with_data,
11440 overrule_keep_as_halo_element_status,
11441 element_to_global_index,
11445 flush_shared_boundary_polyline_pt();
11446 Shared_boundary_polyline_pt.resize(nproc);
11452 std::set<FiniteElement*> element_in_processor_pt;
11453 const unsigned n_ele = backed_up_f_el_pt.size();
11454 for (
unsigned e = 0;
e < n_ele;
e++)
11456 if (element_domain[
e] == my_rank)
11458 element_in_processor_pt.insert(backed_up_f_el_pt[
e]);
11465 std::map<std::pair<Node*,Node*>,
unsigned> elements_edges_on_boundary;
11466 this->get_element_edges_on_boundary(elements_edges_on_boundary);
11470 this->create_polylines_from_halo_elements_helper(element_domain,
11471 element_to_global_index,
11472 element_in_processor_pt,
11474 elements_edges_on_boundary,
11475 Shared_boundary_polyline_pt);
11484 template<
class ELEMENT>
11488 std::map<
Data*,std::set<unsigned> > &processors_associated_with_data,
11489 const bool&overrule_keep_as_halo_element_status,
11490 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11493 const unsigned n_ele = backed_up_el_pt.size();
11496 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11503 for (
unsigned e=0;
e<n_ele;
e++)
11507 unsigned el_domain=element_domain[
e];
11511 if (el_domain!=iproc)
11516 if ((this->Keep_all_elements_as_halos) ||
11519 if (!overrule_keep_as_halo_element_status)
11523 if (!already_added[el_domain][el_pt])
11525 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11526 already_added[el_domain][el_pt] =
true;
11527 element_to_global_index[el_pt] =
e;
11536 if(finite_el_pt!=0)
11538 unsigned n_node = finite_el_pt->
nnode();
11539 for (
unsigned n=0;
n<n_node;
n++)
11544 std::set<unsigned>::iterator it =
11545 processors_associated_with_data[nod_pt].find(iproc);
11546 if (it!=processors_associated_with_data[nod_pt].end())
11550 if (!already_added[el_domain][el_pt])
11552 output_halo_elements_pt[iproc][el_domain].push_back(el_pt);
11553 already_added[el_domain][el_pt] =
true;
11554 element_to_global_index[el_pt] =
e;
11573 template <
class ELEMENT>
11575 std::map<std::pair<Node*,Node*>,
unsigned> &element_edges_on_boundary)
11578 const unsigned nbound = this->nboundary();
11580 for (
unsigned b = 0; b < nbound; b++)
11583 std::map<std::pair<Node*, Node*>,
bool> edge_done;
11585 const unsigned nbound_ele = this->nboundary_element(b);
11586 for (
unsigned e = 0;
e < nbound_ele;
e++)
11591 int face_index = this->face_index_at_boundary(b,
e);
11596 const unsigned nnodes = face_ele_pt->
nnode();
11599 Node* last_node_pt = face_ele_pt->
node_pt(nnodes-1);
11602 std::pair<Node*,Node*> edge =
11603 std::make_pair(first_node_pt, last_node_pt);
11606 if (!edge_done[edge])
11609 edge_done[edge] =
true;
11612 std::pair<Node*,Node*> inv_edge =
11613 std::make_pair(last_node_pt, first_node_pt);
11616 edge_done[inv_edge] =
true;
11619 element_edges_on_boundary[edge] = b;
11623 delete face_ele_pt;
11639 template<
class ELEMENT>
11642 std::map<GeneralisedElement*, unsigned> &element_to_global_index,
11643 std::set<FiniteElement*> &element_in_processor_pt,
11645 std::map<std::pair<Node*,Node*>,
unsigned> &elements_edges_on_boundary,
11648 const unsigned nproc = this->communicator_pt()->nproc();
11649 const unsigned my_rank = this->communicator_pt()->my_rank();
11674 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
11680 Shared_boundaries_ids.resize(nproc);
11681 for (
unsigned j = 0 ; j < nproc; j++)
11683 edges[j].resize(nproc);
11684 edge_element_pt[j].resize(nproc);
11685 edge_element_face[j].resize(nproc);
11686 edge_boundary[j].resize(nproc);
11689 Shared_boundaries_ids[j].resize(nproc);
11695 for (
unsigned iproc = 0; iproc < nproc; iproc++)
11702 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
11719 halo_elements_iproc_with_jproc = input_halo_elements[iproc][jproc];
11722 const unsigned nhalo_elements_iproc_with_jproc =
11723 halo_elements_iproc_with_jproc.size();
11725 if (nhalo_elements_iproc_with_jproc > 0)
11728 halo_elements_jproc_with_iproc = input_halo_elements[jproc][iproc];
11732 const unsigned nhalo_elements_jproc_with_iproc =
11733 halo_elements_jproc_with_iproc.size();
11736 if (nhalo_elements_jproc_with_iproc == 0)
11741 std::stringstream err;
11742 err <<
"There are no halo elements from processor ("<<jproc<<
") "
11743 <<
"with processor ("<<iproc<<
").\n"
11744 <<
"This is strange since there are halo elements from "
11745 <<
"processor ("<<iproc<<
") with processor ("<<jproc<<
").\n"
11746 <<
"Number of halo elements from ("<<iproc<<
") to ("
11747 <<jproc<<
") : ("<< nhalo_elements_iproc_with_jproc<<
")\n"
11748 <<
"Number of halo elements from ("<<jproc<<
") to ("
11749 <<iproc<<
") : ("<< nhalo_elements_jproc_with_iproc<<
")\n";
11751 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11752 OOMPH_EXCEPTION_LOCATION);
11757 unsigned halo_edges_counter_iproc = 0;
11759 unsigned halo_edges_counter_jproc = 0;
11762 std::map<std::pair<Node*,Node*>,
FiniteElement*> edgesi_to_element_pt;
11766 std::map<std::pair<std::pair<Node*,Node*>,
FiniteElement*>,
int>
11767 edgesi_element_pt_to_face_index;
11770 std::map<std::pair<Node*,Node*>,
FiniteElement*> edgesj_to_element_pt;
11774 std::map<std::pair<std::pair<Node*,Node*>,
FiniteElement*>,
int>
11775 edgesj_element_pt_to_face_index;
11781 for (
unsigned ih = 0; ih < nhalo_elements_iproc_with_jproc; ih++)
11785 element_to_global_index[halo_elements_iproc_with_jproc[ih]];
11787 if (element_domain[
e] != jproc)
11790 std::stringstream err;
11791 err <<
"There was a problem on the ihalo-jhalo classification.\n"
11792 <<
"One of the elements, (the one with the ("<<
e<<
")-th "
11793 <<
"index ) is not on the ("<<jproc<<
")-th processor\n"
11794 <<
"but it was stored as a halo element of processor ("
11795 << iproc<<
") with processor ("<<jproc<<
").\n";
11798 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11799 OOMPH_EXCEPTION_LOCATION);
11804 dynamic_cast<FiniteElement*
>(halo_elements_iproc_with_jproc[ih]);
11808 std::stringstream err;
11809 err <<
"The halo element ("<<ih<<
") could not be casted to the "
11810 <<
"FiniteElement type.\n";
11813 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11814 OOMPH_EXCEPTION_LOCATION);
11819 const unsigned n_nodes = el_pt->
nnode();
11826 std::stringstream err;
11827 err <<
"The number of nodes of the "<<ih<<
"-th halo element is"
11828 <<
" ("<< n_nodes <<
").\nWe can not work with triangle "
11829 <<
"elements with less than three nodes\n";
11831 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11832 OOMPH_EXCEPTION_LOCATION);
11842 halo_edges_iproc.push_back(first_node_pt);
11843 halo_edges_iproc.push_back(second_node_pt);
11844 halo_edges_counter_jproc++;
11846 halo_edges_iproc.push_back(second_node_pt);
11847 halo_edges_iproc.push_back(third_node_pt);
11848 halo_edges_counter_jproc++;
11850 halo_edges_iproc.push_back(third_node_pt);
11851 halo_edges_iproc.push_back(first_node_pt);
11852 halo_edges_counter_jproc++;
11855 std::pair<Node*, Node*> edge1 =
11856 std::make_pair(first_node_pt, second_node_pt);
11857 edgesi_to_element_pt[edge1] = el_pt;
11859 std::pair<Node*, Node*> edge2 =
11860 std::make_pair(second_node_pt, third_node_pt);
11861 edgesi_to_element_pt[edge2] = el_pt;
11863 std::pair<Node*, Node*> edge3 =
11864 std::make_pair(third_node_pt, first_node_pt);
11865 edgesi_to_element_pt[edge3] = el_pt;
11868 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
11869 std::make_pair(edge1, el_pt);
11870 edgesi_element_pt_to_face_index[edge_ele1] = 2;
11872 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
11873 std::make_pair(edge2, el_pt);
11874 edgesi_element_pt_to_face_index[edge_ele2] = 0;
11876 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
11877 std::make_pair(edge3, el_pt);
11878 edgesi_element_pt_to_face_index[edge_ele3] = 1;
11886 for (
unsigned jh = 0; jh < nhalo_elements_jproc_with_iproc; jh++)
11890 element_to_global_index[halo_elements_jproc_with_iproc[jh]];
11892 if (element_domain[
e] != iproc)
11895 std::stringstream err;
11896 err <<
"There was a problem on the jhalo-ihalo classification.\n"
11897 <<
"One of the elements, (the one with the ("<<
e<<
")-th "
11898 <<
"index ) is not on the ("<<iproc<<
")-th processor\n"
11899 <<
"but it was stored as a halo element of processor ("
11900 << jproc<<
") with processor ("<<iproc<<
").\n";
11903 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11904 OOMPH_EXCEPTION_LOCATION);
11909 dynamic_cast<FiniteElement*
>(halo_elements_jproc_with_iproc[jh]);
11912 std::stringstream err;
11913 err <<
"The halo element ("<<jh<<
") could not be casted to the "
11914 <<
"FiniteElement type.\n";
11917 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11918 OOMPH_EXCEPTION_LOCATION);
11923 const unsigned n_nodes = el_pt->
nnode();
11930 std::stringstream err;
11931 err <<
"The number of nodes of the "<<jh<<
"-th halo element is"
11932 <<
" ("<< n_nodes <<
").\nWe can not work with triangle "
11933 <<
"elements with less than three nodes\n";
11935 "TriangleMesh::create_polylines_from_halo_elements_helper()",
11936 OOMPH_EXCEPTION_LOCATION);
11946 halo_edges_jproc.push_back(first_node_pt);
11947 halo_edges_jproc.push_back(second_node_pt);
11948 halo_edges_counter_iproc++;
11950 halo_edges_jproc.push_back(second_node_pt);
11951 halo_edges_jproc.push_back(third_node_pt);
11952 halo_edges_counter_iproc++;
11954 halo_edges_jproc.push_back(third_node_pt);
11955 halo_edges_jproc.push_back(first_node_pt);
11956 halo_edges_counter_iproc++;
11959 std::pair<Node*, Node*> edge1 =
11960 std::make_pair(first_node_pt, second_node_pt);
11961 edgesj_to_element_pt[edge1] = el_pt;
11963 std::pair<Node*, Node*> edge2 =
11964 std::make_pair(second_node_pt, third_node_pt);
11965 edgesj_to_element_pt[edge2] = el_pt;
11967 std::pair<Node*, Node*> edge3 =
11968 std::make_pair(third_node_pt, first_node_pt);
11969 edgesj_to_element_pt[edge3] = el_pt;
11972 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele1 =
11973 std::make_pair(edge1, el_pt);
11974 edgesj_element_pt_to_face_index[edge_ele1] = 2;
11976 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele2 =
11977 std::make_pair(edge2, el_pt);
11978 edgesj_element_pt_to_face_index[edge_ele2] = 0;
11980 std::pair<std::pair<Node*, Node*>,
FiniteElement*> edge_ele3 =
11981 std::make_pair(edge3, el_pt);
11982 edgesj_element_pt_to_face_index[edge_ele3] = 1;
11995 unsigned nhalo_iedges = halo_edges_iproc.size();
11996 unsigned nhalo_jedges = halo_edges_jproc.size();
12000 for (
unsigned ihe = 0; ihe < nhalo_iedges; ihe+=2)
12004 ihalo_edge[0] = halo_edges_iproc[ihe];
12005 ihalo_edge[1] = halo_edges_iproc[ihe+1];
12008 std::pair<Node*,Node*> tmp_edge = std::make_pair(ihalo_edge[0],
12013 int edge_boundary_id = -1;
12015 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
12016 it = elements_edges_on_boundary.find(tmp_edge);
12019 if (it != elements_edges_on_boundary.end())
12023 edge_boundary_id = (*it).second;
12029 std::pair<Node*,Node*> rtmp_edge = std::make_pair(ihalo_edge[1],
12031 it = elements_edges_on_boundary.find(rtmp_edge);
12032 if (it != elements_edges_on_boundary.end())
12036 edge_boundary_id = (*it).second;
12043 for (
unsigned jhe = 0; jhe < nhalo_jedges; jhe+=2)
12047 jhalo_edge[0] = halo_edges_jproc[jhe];
12048 jhalo_edge[1] = halo_edges_jproc[jhe+1];
12051 if (ihalo_edge[0] == jhalo_edge[0] &&
12052 ihalo_edge[1] == jhalo_edge[1])
12055 std::pair<Node*, Node*> new_edge =
12056 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12062 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12064 haloj_ele_pt = edgesj_to_element_pt[new_edge];
12067 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12069 std::stringstream err;
12070 err <<
"There is no associated elements with the new "
12071 <<
"shared boundary. This is an storing problem,\n"
12072 <<
"possibly related with a memory leak problem!!!\n"
12073 <<
"The nodes that compound the edge are these:\n"
12074 <<
"On processor ("<<iproc<<
"):\n"
12075 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12076 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12077 <<ihalo_edge[1]->x(1)<<
")\n\n"
12078 <<
"On processor ("<<jproc<<
"):\n"
12079 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12080 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12081 <<jhalo_edge[1]->x(1)<<
")\n\n"
12082 <<
"The nodes coordinates should be the same!!!\n";
12084 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12085 OOMPH_EXCEPTION_LOCATION);
12089 edges[iproc][jproc].push_back(new_edge);
12092 if (edge_boundary_id >= 0)
12095 overlapped_edge[new_edge] =
true;
12098 std::pair<Node*, Node*> rev_new_edge =
12099 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12102 overlapped_edge[rev_new_edge] =
true;
12108 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12112 tmp_elements_pt.push_back(haloi_ele_pt);
12113 tmp_elements_pt.push_back(haloj_ele_pt);
12116 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12123 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12126 edge_elementj_pair = make_pair(new_edge, haloj_ele_pt);
12130 int face_index_haloi_ele = -1;
12131 face_index_haloi_ele =
12132 edgesi_element_pt_to_face_index[edge_elementi_pair];
12133 int face_index_haloj_ele = -1;
12134 face_index_haloj_ele =
12135 edgesj_element_pt_to_face_index[edge_elementj_pair];
12137 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12139 std::stringstream err;
12140 err <<
"There is no associated face indexes to the"
12141 <<
"elements that gave\nrise to the shared edge\n"
12142 <<
"The nodes that compound the edge are these:\n"
12143 <<
"On processor ("<<iproc<<
"):\n"
12144 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12145 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12146 <<ihalo_edge[1]->x(1)<<
")\n\n"
12147 <<
"On processor ("<<jproc<<
"):\n"
12148 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12149 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12150 <<jhalo_edge[1]->x(1)<<
")\n\n"
12151 <<
"The nodes coordinates should be the same!!!\n";
12153 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12154 OOMPH_EXCEPTION_LOCATION);
12160 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12161 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12163 edge_element_face[iproc][jproc].
12164 push_back(tmp_edge_element_face_index);
12172 else if (ihalo_edge[0] == jhalo_edge[1] &&
12173 ihalo_edge[1] == jhalo_edge[0])
12176 std::pair<Node*, Node*> new_edge =
12177 std::make_pair(ihalo_edge[0], ihalo_edge[1]);
12182 haloi_ele_pt = edgesi_to_element_pt[new_edge];
12187 std::pair<Node*, Node*> new_edge_reversed =
12188 std::make_pair(jhalo_edge[0], jhalo_edge[1]);
12189 haloj_ele_pt = edgesj_to_element_pt[new_edge_reversed];
12192 if (haloi_ele_pt == 0 || haloj_ele_pt == 0)
12194 std::stringstream err;
12195 err <<
"There is no associated elements with the new "
12196 <<
"shared boundary (reversed version). This is an "
12197 <<
"storing problem, possibly related with a memory "
12198 <<
"leak problem!!!\n"
12199 <<
"The nodes that compound the edge are these:\n"
12200 <<
"On processor ("<<iproc<<
"):\n"
12201 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12202 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12203 <<ihalo_edge[1]->x(1)<<
")\n\n"
12204 <<
"On processor ("<<jproc<<
"):\n"
12205 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12206 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12207 <<jhalo_edge[1]->x(1)<<
")\n\n"
12208 <<
"The nodes coordinates should be the same!!!\n";
12210 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12211 OOMPH_EXCEPTION_LOCATION);
12215 edges[iproc][jproc].push_back(new_edge);
12218 if (edge_boundary_id >= 0)
12221 overlapped_edge[new_edge] =
true;
12224 std::pair<Node*, Node*> rev_new_edge =
12225 std::make_pair(ihalo_edge[1], ihalo_edge[0]);
12228 overlapped_edge[rev_new_edge] =
true;
12233 edge_boundary[iproc][jproc].push_back(edge_boundary_id);
12237 tmp_elements_pt.push_back(haloi_ele_pt);
12238 tmp_elements_pt.push_back(haloj_ele_pt);
12241 edge_element_pt[iproc][jproc].push_back(tmp_elements_pt);
12248 edge_elementi_pair = make_pair(new_edge, haloi_ele_pt);
12251 edge_elementj_pair = make_pair(new_edge_reversed,
12256 int face_index_haloi_ele = -1;
12257 face_index_haloi_ele =
12258 edgesi_element_pt_to_face_index[edge_elementi_pair];
12259 int face_index_haloj_ele = -1;
12260 face_index_haloj_ele =
12261 edgesj_element_pt_to_face_index[edge_elementj_pair];
12263 if (face_index_haloi_ele == -1 || face_index_haloj_ele == -1)
12265 std::stringstream err;
12266 err <<
"There is no associated face indexes to the"
12267 <<
"elements that gave\nrise to the shared edge\n"
12268 <<
"The nodes that compound the edge are these:\n"
12269 <<
"On processor ("<<iproc<<
"):\n"
12270 <<
"("<<ihalo_edge[0]->x(0)<<
", "<<ihalo_edge[0]->x(1)
12271 <<
") and ("<<ihalo_edge[1]->x(0)<<
", "
12272 <<ihalo_edge[1]->x(1)<<
")\n\n"
12273 <<
"On processor ("<<jproc<<
"):\n"
12274 <<
"("<<jhalo_edge[0]->x(0)<<
", "<<jhalo_edge[0]->x(1)
12275 <<
") and ("<<jhalo_edge[1]->x(0)<<
", "
12276 <<jhalo_edge[1]->x(1)<<
")\n\n"
12277 <<
"The nodes coordinates should be the same!!!\n";
12279 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12280 OOMPH_EXCEPTION_LOCATION);
12286 tmp_edge_element_face_index.push_back(face_index_haloi_ele);
12287 tmp_edge_element_face_index.push_back(face_index_haloj_ele);
12289 edge_element_face[iproc][jproc].
12290 push_back(tmp_edge_element_face_index);
12315 std::map<Node*, unsigned> global_shared_node_degree;
12319 std::map<std::pair<Node*, Node*>,
bool> edge_done;
12320 #endif // #ifdef PARANOID
12322 std::map<Node*,bool> node_done;
12326 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12333 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12336 const unsigned nshd_edges = edges[iproc][jproc].size();
12342 const unsigned nedge_element = edge_element_pt[iproc][jproc].size();
12343 if (nshd_edges != nedge_element)
12345 std::stringstream error_message;
12347 <<
"The number of shared edges between processor iproc and jproc\n"
12348 <<
"is different form the number of edge elements between the\n"
12349 <<
"pair of processors\n"
12350 <<
"iproc: (" << iproc <<
")\n"
12351 <<
"jproc: (" << jproc <<
")\n"
12352 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12353 <<
"# of edge elements: (" << nedge_element <<
")\n\n";
12355 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12356 OOMPH_EXCEPTION_LOCATION);
12360 const unsigned nedge_element_face =
12361 edge_element_face[iproc][jproc].size();
12362 if (nshd_edges != nedge_element_face)
12364 std::stringstream error_message;
12366 <<
"The number of shared edges between processor iproc and jproc\n"
12367 <<
"is different form the number of edge element faces between the\n"
12368 <<
"pair of processors\n"
12369 <<
"iproc: (" << iproc <<
")\n"
12370 <<
"jproc: (" << jproc <<
")\n"
12371 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12372 <<
"# of edge element faces: (" << nedge_element_face <<
")\n\n";
12374 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12375 OOMPH_EXCEPTION_LOCATION);
12379 const unsigned nedge_boundary = edge_boundary[iproc][jproc].size();
12380 if (nshd_edges != nedge_boundary)
12382 std::stringstream error_message;
12384 <<
"The number of shared edges between processor iproc and jproc\n"
12385 <<
"is different form the number of edge boundaries ids between the\n"
12386 <<
"pair of processors\n"
12387 <<
"iproc: (" << iproc <<
")\n"
12388 <<
"jproc: (" << jproc <<
")\n"
12389 <<
"# of shared edges: (" << nshd_edges <<
")\n"
12390 <<
"# of edge boundaries ids: (" << nedge_boundary <<
")\n\n";
12392 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12393 OOMPH_EXCEPTION_LOCATION);
12396 #endif // #ifdef PARANOID
12399 for (
unsigned se = 0; se < nshd_edges; se++)
12402 std::pair<Node*, Node*> edge = edges[iproc][jproc][se];
12405 if (edge_done[edge])
12407 std::stringstream error_message;
12409 <<
"The shared edge between processor iproc and processor\n"
12410 <<
"jproc has been already visited, this is weird since the\n"
12411 <<
"edge should not be shared by other pair of processors\n"
12412 <<
"iproc: (" << iproc <<
")\n"
12413 <<
"jproc: (" << jproc <<
")\n"
12414 <<
"First node of edge: (" << edge.first->x(0) <<
", "
12415 << edge.first->x(1) <<
")\n"
12416 <<
"Second node of edge: (" << edge.second->x(0) <<
", "
12417 << edge.second->x(1) <<
")\n"
12418 <<
"Associated edge boundary id: ("
12419 << edge_boundary[iproc][jproc][se] <<
")\n\n";
12421 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12422 OOMPH_EXCEPTION_LOCATION);
12426 edge_done[edge] =
true;
12428 std::pair<Node*, Node*> rev_edge =
12429 std::make_pair(edge.second, edge.first);
12431 edge_done[rev_edge] =
true;
12432 #endif // #ifdef PARANOID
12435 Node* left_node_pt = edge.first;
12436 Node* right_node_pt = edge.second;
12439 if (!node_done[left_node_pt])
12443 global_shared_node_degree[left_node_pt] = 1;
12449 global_shared_node_degree[left_node_pt]++;
12453 if (!node_done[right_node_pt])
12457 global_shared_node_degree[right_node_pt] = 1;
12462 global_shared_node_degree[right_node_pt]++;
12477 std::map<unsigned, std::map<Node*, bool> >
12478 node_on_bnd_not_overlapped_by_shd_bnd;
12481 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
12482 elements_edges_on_boundary.begin();
12483 it_map != elements_edges_on_boundary.end(); it_map++)
12486 std::pair<Node*,Node*> edge_pair = (*it_map).first;
12489 if (!overlapped_edge[edge_pair])
12493 unsigned b = (*it_map).second;
12496 Node* left_node_pt = edge_pair.first;
12497 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
12500 Node* right_node_pt = edge_pair.second;
12501 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
12521 std::map<unsigned, std::list<Node*> > shared_bnd_id_to_sorted_list_node_pt;
12525 unsigned shared_boundary_id_start = this->nboundary();
12526 Initial_shared_boundary_id = shared_boundary_id_start;
12532 for (
unsigned iproc = 0; iproc < nproc; iproc++)
12539 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
12547 unsigned npolylines_counter = 0;
12548 const unsigned nedges = edges[iproc][jproc].size();
12554 unsigned nsorted_edges = 0;
12557 std::map<std::pair<Node*,Node*>,
bool> edge_done;
12561 while(nsorted_edges < nedges)
12565 std::list<FiniteElement*> tmp_boundary_element_pt;
12568 std::list<int> tmp_face_index_element;
12570 std::pair<Node*,Node*> edge;
12572 bool found_initial_edge =
false;
12574 int root_edge_bound_id = -1;
12575 unsigned iedge = 0;
12576 for (iedge = 0; iedge < nedges; iedge++)
12578 edge = edges[iproc][jproc][iedge];
12580 if (!edge_done[edge])
12583 root_edge_bound_id = edge_boundary[iproc][jproc][iedge];
12585 found_initial_edge =
true;
12594 if (!found_initial_edge)
12596 std::ostringstream error_message;
12598 <<
"All the edge are already done, but the number of done\n"
12599 <<
"edges ("<<nsorted_edges<<
") is still less than the total\n"
12600 <<
"number of edges (" << nedges <<
").\n";
12603 "TriangleMesh::create_polylines_from_halo_elements_helper()",
12604 OOMPH_EXCEPTION_LOCATION);
12610 std::list<Node*> sorted_nodes;
12611 sorted_nodes.clear();
12614 Node *first_node_pt = edge.first;
12615 Node *last_node_pt = edge.second;
12618 sorted_nodes.push_back(first_node_pt);
12619 sorted_nodes.push_back(last_node_pt);
12623 tmp_boundary_element_pt.
12624 push_back(edge_element_pt[iproc][jproc][iedge-1][0]);
12625 tmp_boundary_element_pt.
12626 push_back(edge_element_pt[iproc][jproc][iedge-1][1]);
12630 tmp_face_index_element.
12631 push_back(edge_element_face[iproc][jproc][iedge-1][0]);
12632 tmp_face_index_element.
12633 push_back(edge_element_face[iproc][jproc][iedge-1][1]);
12636 edge_done[edge] =
true;
12641 bool node_added =
true;
12645 bool node_added_to_the_left =
true;
12646 bool node_added_to_the_right =
true;
12664 bool connection_to_the_left =
false;
12669 bool connection_to_the_right =
false;
12673 bool current_polyline_has_connections_at_both_ends =
false;
12680 int bound_id_connection_to_the_left = -1;
12681 int bound_id_connection_to_the_right = -1;
12684 const unsigned first_node_degree =
12685 global_shared_node_degree[first_node_pt];
12689 bound_id_connection_to_the_left =
12690 check_connections_of_polyline_nodes(
12691 element_in_processor_pt,
12692 root_edge_bound_id,
12694 node_on_bnd_not_overlapped_by_shd_bnd,
12696 shared_bnd_id_to_sorted_list_node_pt,
12706 if (bound_id_connection_to_the_left != -1)
12708 connection_to_the_left =
true;
12712 const unsigned last_node_degree =
12713 global_shared_node_degree[last_node_pt];
12717 bound_id_connection_to_the_right =
12718 check_connections_of_polyline_nodes(
12719 element_in_processor_pt,
12720 root_edge_bound_id,
12722 node_on_bnd_not_overlapped_by_shd_bnd,
12724 shared_bnd_id_to_sorted_list_node_pt,
12733 if (bound_id_connection_to_the_right != -1)
12735 connection_to_the_right =
true;
12740 if (connection_to_the_left && connection_to_the_right)
12741 {current_polyline_has_connections_at_both_ends =
true;}
12748 while(node_added && (nsorted_edges < nedges)
12749 && !current_polyline_has_connections_at_both_ends)
12754 for (
unsigned iiedge = iedge; iiedge < nedges; iiedge++)
12757 node_added =
false;
12758 node_added_to_the_left =
false;
12759 node_added_to_the_right =
false;
12761 edge = edges[iproc][jproc][iiedge];
12762 const int edge_bound_id = edge_boundary[iproc][jproc][iiedge];
12768 if (!edge_done[edge] &&
12769 (edge_bound_id == root_edge_bound_id))
12772 Node* left_node_pt = edge.first;
12773 Node* right_node_pt = edge.second;
12776 Node* new_added_node_pt = 0;
12779 if (left_node_pt == first_node_pt &&
12780 !connection_to_the_left)
12783 sorted_nodes.push_front(right_node_pt);
12785 new_added_node_pt = first_node_pt = right_node_pt;
12789 node_added_to_the_left =
true;
12792 else if (left_node_pt == last_node_pt &&
12793 !connection_to_the_right)
12796 sorted_nodes.push_back(right_node_pt);
12798 new_added_node_pt = last_node_pt = right_node_pt;
12802 node_added_to_the_right =
true;
12805 else if (right_node_pt == first_node_pt &&
12806 !connection_to_the_left)
12809 sorted_nodes.push_front(left_node_pt);
12811 new_added_node_pt = first_node_pt = left_node_pt;
12815 node_added_to_the_left =
true;
12818 else if (right_node_pt == last_node_pt &&
12819 !connection_to_the_right)
12822 sorted_nodes.push_back(left_node_pt);
12824 new_added_node_pt = last_node_pt = left_node_pt;
12828 node_added_to_the_right =
true;
12838 edge_done[edge] =
true;
12842 const unsigned added_node_degree =
12843 global_shared_node_degree[new_added_node_pt];
12845 if (node_added_to_the_left)
12848 tmp_boundary_element_pt.push_front(
12849 edge_element_pt[iproc][jproc][iiedge][1]);
12850 tmp_boundary_element_pt.push_front(
12851 edge_element_pt[iproc][jproc][iiedge][0]);
12853 tmp_face_index_element.push_front(
12854 edge_element_face[iproc][jproc][iiedge][1]);
12855 tmp_face_index_element.push_front(
12856 edge_element_face[iproc][jproc][iiedge][0]);
12859 if (node_added_to_the_right)
12862 tmp_boundary_element_pt.push_back(
12863 edge_element_pt[iproc][jproc][iiedge][0]);
12864 tmp_boundary_element_pt.push_back(
12865 edge_element_pt[iproc][jproc][iiedge][1]);
12867 tmp_face_index_element.push_back(
12868 edge_element_face[iproc][jproc][iiedge][0]);
12869 tmp_face_index_element.push_back(
12870 edge_element_face[iproc][jproc][iiedge][1]);
12880 if (node_added_to_the_left && !connection_to_the_left)
12883 bound_id_connection_to_the_left =
12884 check_connections_of_polyline_nodes(
12885 element_in_processor_pt,
12886 root_edge_bound_id,
12888 node_on_bnd_not_overlapped_by_shd_bnd,
12890 shared_bnd_id_to_sorted_list_node_pt,
12892 new_added_node_pt);
12899 if (bound_id_connection_to_the_left != -1)
12901 connection_to_the_left =
true;
12911 if (node_added_to_the_right && !connection_to_the_right)
12914 bound_id_connection_to_the_right =
12915 check_connections_of_polyline_nodes(
12916 element_in_processor_pt,
12917 root_edge_bound_id,
12919 node_on_bnd_not_overlapped_by_shd_bnd,
12921 shared_bnd_id_to_sorted_list_node_pt,
12923 new_added_node_pt);
12930 if (bound_id_connection_to_the_right != -1)
12932 connection_to_the_right =
true;
12940 if (connection_to_the_left && connection_to_the_right)
12941 {current_polyline_has_connections_at_both_ends =
true;}
12964 const unsigned n_bnd_ele = tmp_boundary_element_pt.size();
12970 unsigned help_counter = 0;
12972 for (std::list<FiniteElement*>::iterator it_bnd_ele =
12973 tmp_boundary_element_pt.begin();
12974 it_bnd_ele != tmp_boundary_element_pt.end();
12977 tmp_bnd_ele_pt[help_counter++] = (*it_bnd_ele);
12982 for (std::list<int>::iterator it_face_idx =
12983 tmp_face_index_element.begin();
12984 it_face_idx != tmp_face_index_element.end();
12987 tmp_face_idx_ele[help_counter++] = (*it_face_idx);
13000 Vector<int> final_bound_id_connection_to_the_left;
13003 Vector<int> final_bound_id_connection_to_the_right;
13006 break_loops_on_shared_polyline_helper(
13007 shared_boundary_id_start,
13009 tmp_bnd_ele_pt, tmp_face_idx_ele,
13010 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
13011 final_sorted_nodes_pt,
13012 final_boundary_element_pt, final_face_index_element,
13013 final_bound_id_connection_to_the_left,
13014 final_bound_id_connection_to_the_right);
13017 const unsigned n_final_sorted_nodes =
13018 final_sorted_nodes_pt.size();
13021 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
13026 shared_bnd_id_to_sorted_list_node_pt[shared_boundary_id_start] =
13027 final_sorted_nodes_pt[
i];
13031 create_shared_polyline(my_rank, shared_boundary_id_start,
13032 iproc, jproc, final_sorted_nodes_pt[
i],
13033 root_edge_bound_id,
13034 final_boundary_element_pt[
i],
13035 final_face_index_element[
i],
13036 unsorted_polylines_pt,
13037 final_bound_id_connection_to_the_left[
i],
13038 final_bound_id_connection_to_the_right[
i]);
13042 npolylines_counter++;
13046 shared_boundary_id_start++;
13059 if (unsorted_polylines_pt[iproc].size() > 0)
13063 sort_polylines_helper(unsorted_polylines_pt[iproc],
13064 output_polylines_pt[iproc]);
13068 const unsigned nunsorted_polylines_iproc =
13069 unsorted_polylines_pt[iproc].size();
13072 unsigned tmp_ntotal_polylines = 0;
13074 for (
unsigned ii = 0 ; ii < output_polylines_pt[iproc].size(); ii++)
13075 {tmp_ntotal_polylines+= output_polylines_pt[iproc][ii].size();}
13076 if (tmp_ntotal_polylines != nunsorted_polylines_iproc)
13078 std::ostringstream error_message;
13080 <<
" The total number of unsorted polylines ("
13081 << nunsorted_polylines_iproc <<
") in common with\nprocessor ("
13082 << iproc<<
") is different from the total number of sorted "
13083 <<
"polylines (" << tmp_ntotal_polylines <<
") with\nthe same "
13086 OOMPH_CURRENT_FUNCTION,
13087 OOMPH_EXCEPTION_LOCATION);
13094 this->Final_shared_boundary_id = shared_boundary_id_start;
13102 template<
class ELEMENT>
13104 const unsigned &initial_shd_bnd_id,
13105 std::list<Node*> &input_nodes,
13108 const int &input_connect_to_the_left,
13109 const int &input_connect_to_the_right,
13110 Vector<std::list<Node*> > &output_sorted_nodes_pt,
13117 Node* left_node_pt = input_nodes.front();
13118 Node* right_node_pt = input_nodes.back();
13127 std::list<Node*>::iterator it = input_nodes.begin();
13130 unsigned counter = 0;
13133 while(it != input_nodes.end())
13138 if (it == input_nodes.end())
13150 std::list<Node*> sub_nodes;
13159 sub_nodes.push_back(*it);
13169 sub_nodes.push_back((*it));
13172 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
13173 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter+1]);
13176 sub_face_idx_ele.push_back(input_face_index_element[counter]);
13177 sub_face_idx_ele.push_back(input_face_index_element[counter+1]);
13184 }
while((*it) != left_node_pt &&
13185 (*it) != right_node_pt &&
13186 it != input_nodes.end());
13189 tmp_sub_nodes.push_back(sub_nodes);
13191 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
13193 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
13201 const unsigned n_sub_list = tmp_sub_nodes.size();
13204 if (n_sub_list > 3)
13206 std::stringstream error_message;
13208 <<
"The number of sub-list of nodes created from the shared\n"
13209 <<
"polyline with loops was (" << n_sub_list <<
").\n"
13210 <<
"We can only handle up to three sub-list of nodes\n";
13212 OOMPH_CURRENT_FUNCTION,
13213 OOMPH_EXCEPTION_LOCATION);
13219 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
13227 output_sorted_nodes_pt = tmp_sub_nodes;
13229 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
13231 output_face_index_element = tmp_sub_face_idx_ele;
13237 if (input_connect_to_the_left == -2)
13239 std::stringstream error_message;
13241 <<
"The connection flag to the left ("
13242 << input_connect_to_the_left <<
") indicates a connection\n"
13243 <<
"with the same polyline.\n However, only one sub-polyline was "
13244 <<
"found and no loop\nwas identified\n\n";
13246 OOMPH_CURRENT_FUNCTION,
13247 OOMPH_EXCEPTION_LOCATION);
13252 if (input_connect_to_the_left == -3)
13254 output_connect_to_the_left.push_back(-1);
13258 output_connect_to_the_left.push_back(input_connect_to_the_left);
13262 if (input_connect_to_the_right == -2)
13264 std::stringstream error_message;
13266 <<
"The connection flag to the right ("
13267 << input_connect_to_the_right <<
") indicates a connection\n"
13268 <<
"with the same polyline.\n However, only one sub-polyline was "
13269 <<
"found and no loop\nwas identified\n\n";
13271 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13272 OOMPH_EXCEPTION_LOCATION);
13277 if (input_connect_to_the_right == -3)
13279 output_connect_to_the_right.push_back(-1);
13283 output_connect_to_the_right.push_back(input_connect_to_the_right);
13291 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
13299 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
13300 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
13303 if (left_sub_node_pt == right_sub_node_pt)
13309 std::list<Node*> first_half_node_pt;
13310 std::list<Node*> second_half_node_pt;
13319 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
13323 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13328 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
13331 first_half_node_pt.push_back(*it_sub);
13337 unsigned counter_nodes = 0;
13338 unsigned counter2 = 0;
13341 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13344 first_half_node_pt.push_back(*it_sub);
13347 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13348 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13350 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13351 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13359 if (counter_nodes == n_sub_nodes_half)
13370 second_half_node_pt.push_back(*it_sub);
13376 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
13379 second_half_node_pt.push_back(*it_sub);
13382 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
13383 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2+1]);
13385 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
13386 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2+1]);
13394 output_sorted_nodes_pt.push_back(first_half_node_pt);
13395 output_sorted_nodes_pt.push_back(second_half_node_pt);
13398 output_boundary_element_pt.push_back(first_half_ele_pt);
13399 output_boundary_element_pt.push_back(second_half_ele_pt);
13402 output_face_index_element.push_back(first_half_face_idx);
13403 output_face_index_element.push_back(second_half_face_idx);
13414 if (input_connect_to_the_left == -3)
13417 output_connect_to_the_left.push_back(-1);
13420 else if (input_connect_to_the_left == -2)
13423 output_connect_to_the_left.push_back(-1);
13428 output_connect_to_the_left.push_back(input_connect_to_the_left);
13434 output_connect_to_the_right.push_back(-1);
13445 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13451 if (n_sub_list == 1)
13453 if (input_connect_to_the_right == -3)
13456 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13458 else if (input_connect_to_the_right == -2)
13461 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13463 else if (input_connect_to_the_right == -1)
13466 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13471 output_connect_to_the_right.push_back(input_connect_to_the_right);
13477 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13490 output_sorted_nodes_pt.push_back(tmp_sub_nodes[0]);
13493 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[0]);
13496 output_face_index_element.push_back(tmp_sub_face_idx_ele[0]);
13504 if (input_connect_to_the_left == -3)
13507 output_connect_to_the_left.push_back(-1);
13510 else if (input_connect_to_the_left == -2)
13513 output_connect_to_the_left.push_back(tmp_shd_bnd_id+1);
13518 output_connect_to_the_left.push_back(input_connect_to_the_left);
13524 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13532 if (n_sub_list > 1)
13536 left_sub_node_pt = tmp_sub_nodes[1].front();
13537 right_sub_node_pt = tmp_sub_nodes[1].back();
13540 if (left_sub_node_pt == right_sub_node_pt)
13546 std::list<Node*> first_half_node_pt;
13547 std::list<Node*> second_half_node_pt;
13556 const unsigned n_sub_nodes = tmp_sub_nodes[1].size();
13560 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13565 std::list<Node*>::iterator it_sub = tmp_sub_nodes[1].begin();
13568 first_half_node_pt.push_back(*it_sub);
13574 unsigned counter_nodes = 0;
13575 unsigned counter2 = 0;
13578 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13581 first_half_node_pt.push_back(*it_sub);
13583 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13584 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13586 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13587 first_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13595 if (counter_nodes == n_sub_nodes_half)
13606 second_half_node_pt.push_back(*it_sub);
13612 for (;it_sub != tmp_sub_nodes[1].end(); it_sub++)
13615 second_half_node_pt.push_back(*it_sub);
13617 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2]);
13618 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[1][counter2+1]);
13620 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2]);
13621 second_half_face_idx.push_back(tmp_sub_face_idx_ele[1][counter2+1]);
13629 output_sorted_nodes_pt.push_back(first_half_node_pt);
13630 output_sorted_nodes_pt.push_back(second_half_node_pt);
13633 output_boundary_element_pt.push_back(first_half_ele_pt);
13634 output_boundary_element_pt.push_back(second_half_ele_pt);
13637 output_face_index_element.push_back(first_half_face_idx);
13638 output_face_index_element.push_back(second_half_face_idx);
13649 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13654 output_connect_to_the_right.push_back(-1);
13665 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13671 if (n_sub_list == 2)
13674 if (input_connect_to_the_right == -1)
13677 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13680 else if (input_connect_to_the_right == -2)
13683 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13686 else if (input_connect_to_the_right == -3)
13689 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13694 output_connect_to_the_right.push_back(input_connect_to_the_right);
13704 std::stringstream error_message;
13706 <<
"The second sub-list of nodes creates a loop but this is not\n"
13707 <<
"the last list of sub-nodes.\n"
13708 <<
"This configuration is not supported\n";
13710 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13711 OOMPH_EXCEPTION_LOCATION);
13722 output_sorted_nodes_pt.push_back(tmp_sub_nodes[1]);
13725 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[1]);
13728 output_face_index_element.push_back(tmp_sub_face_idx_ele[1]);
13736 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13742 if (n_sub_list == 2)
13745 if (input_connect_to_the_right == -3)
13748 output_connect_to_the_right.push_back(-1);
13752 else if (input_connect_to_the_right == -2)
13754 std::stringstream error_message;
13756 <<
"The connection flag to the right ("
13757 << input_connect_to_the_right <<
") indicates a connection\n"
13758 <<
"with the same polyline.\n However, the second sub-list of\n"
13759 <<
"nodes was found not making a loop so no connection with\n"
13760 <<
"itself should be marked\n\n";
13762 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13763 OOMPH_EXCEPTION_LOCATION);
13769 output_connect_to_the_right.push_back(input_connect_to_the_right);
13775 output_connect_to_the_right.push_back(tmp_shd_bnd_id+1);
13786 if (n_sub_list > 2)
13790 left_sub_node_pt = tmp_sub_nodes[2].front();
13791 right_sub_node_pt = tmp_sub_nodes[2].back();
13794 if (left_sub_node_pt == right_sub_node_pt)
13800 std::list<Node*> first_half_node_pt;
13801 std::list<Node*> second_half_node_pt;
13810 const unsigned n_sub_nodes = tmp_sub_nodes[2].size();
13814 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
13819 std::list<Node*>::iterator it_sub = tmp_sub_nodes[2].begin();
13822 first_half_node_pt.push_back(*it_sub);
13828 unsigned counter_nodes = 0;
13829 unsigned counter2 = 0;
13832 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13835 first_half_node_pt.push_back(*it_sub);
13837 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13838 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13840 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13841 first_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13849 if (counter_nodes == n_sub_nodes_half)
13860 second_half_node_pt.push_back(*it_sub);
13866 for (;it_sub != tmp_sub_nodes[2].end(); it_sub++)
13869 second_half_node_pt.push_back(*it_sub);
13871 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2]);
13872 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[2][counter2+1]);
13874 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2]);
13875 second_half_face_idx.push_back(tmp_sub_face_idx_ele[2][counter2+1]);
13883 output_sorted_nodes_pt.push_back(first_half_node_pt);
13884 output_sorted_nodes_pt.push_back(second_half_node_pt);
13887 output_boundary_element_pt.push_back(first_half_ele_pt);
13888 output_boundary_element_pt.push_back(second_half_ele_pt);
13891 output_face_index_element.push_back(first_half_face_idx);
13892 output_face_index_element.push_back(second_half_face_idx);
13900 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13905 output_connect_to_the_right.push_back(-1);
13916 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13920 if (input_connect_to_the_right == -3)
13923 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13925 else if (input_connect_to_the_right == -2)
13928 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13930 else if (input_connect_to_the_right == -1)
13933 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
13938 output_connect_to_the_right.push_back(input_connect_to_the_right);
13951 output_sorted_nodes_pt.push_back(tmp_sub_nodes[2]);
13954 output_boundary_element_pt.push_back(tmp_sub_bnd_ele_pt[2]);
13957 output_face_index_element.push_back(tmp_sub_face_idx_ele[2]);
13965 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
13970 if (input_connect_to_the_right == -3)
13972 std::stringstream error_message;
13974 <<
"The connection flag to the right ("
13975 << input_connect_to_the_right <<
") indicates 'no connection and\n"
13976 <<
"stop adding nodes'.\n However, the thrid sub-list of\n"
13977 <<
"nodes must have a connection to the right with the same\n"
13978 <<
"shared polyline or with any other polyline\n\n";
13980 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13981 OOMPH_EXCEPTION_LOCATION);
13983 else if (input_connect_to_the_right == -1)
13985 std::stringstream error_message;
13987 <<
"The connection flag to the right ("
13988 << input_connect_to_the_right <<
") indicates 'no connection.\n"
13989 <<
"However, the thrid sub-list of nodes must have a connection\n"
13990 <<
"to the right with the same shared polyline or with any other\n"
13993 "TriangleMesh::break_loops_on_shared_polyline_helper()",
13994 OOMPH_EXCEPTION_LOCATION);
13997 else if (input_connect_to_the_right == -2)
14000 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14005 output_connect_to_the_right.push_back(input_connect_to_the_right);
14021 template<
class ELEMENT>
14024 const unsigned &initial_shd_bnd_id,
14025 std::list<Node*> &input_nodes,
14029 const int &input_connect_to_the_left,
14030 const int &input_connect_to_the_right,
14031 Vector<std::list<Node*> > &output_sorted_nodes_pt,
14039 Node* left_node_pt = input_nodes.front();
14040 Node* right_node_pt = input_nodes.back();
14050 std::list<Node*>::iterator it = input_nodes.begin();
14053 unsigned counter = 0;
14056 while(it != input_nodes.end())
14061 if (it == input_nodes.end())
14073 std::list<Node*> sub_nodes;
14085 sub_nodes.push_back(*it);
14095 sub_nodes.push_back((*it));
14098 sub_bnd_ele_pt.push_back(input_boundary_element_pt[counter]);
14101 sub_bnd_face_ele_pt.push_back(input_boundary_face_element_pt[counter]);
14104 sub_face_idx_ele.push_back(input_face_index_element[counter]);
14111 }
while((*it) != left_node_pt &&
14112 (*it) != right_node_pt &&
14113 it != input_nodes.end());
14116 tmp_sub_nodes.push_back(sub_nodes);
14119 tmp_sub_bnd_ele_pt.push_back(sub_bnd_ele_pt);
14121 tmp_sub_bnd_face_ele_pt.push_back(sub_bnd_face_ele_pt);
14123 tmp_sub_face_idx_ele.push_back(sub_face_idx_ele);
14131 const unsigned n_sub_list = tmp_sub_nodes.size();
14134 if (n_sub_list > 1)
14136 std::stringstream error_message;
14138 <<
"The number of sub-list of nodes created from the shared\n"
14139 <<
"polyline with loops was (" << n_sub_list <<
").\n"
14140 <<
"We can only handle one list which may still contain loops\n"
14141 <<
"(or repeated nodes)\n";
14143 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14144 OOMPH_EXCEPTION_LOCATION);
14150 if (n_sub_list == 1 && (left_node_pt != right_node_pt))
14158 output_sorted_nodes_pt = tmp_sub_nodes;
14160 output_boundary_element_pt = tmp_sub_bnd_ele_pt;
14162 output_boundary_face_element_pt = tmp_sub_bnd_face_ele_pt;
14164 output_face_index_element = tmp_sub_face_idx_ele;
14170 if (input_connect_to_the_left == -2)
14172 std::stringstream error_message;
14174 <<
"The connection flag to the left ("
14175 << input_connect_to_the_left <<
") indicates a connection\n"
14176 <<
"with the same polyline.\n However, only one sub-polyline was "
14177 <<
"found and no loops\nwere identified\n\n";
14179 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14180 OOMPH_EXCEPTION_LOCATION);
14185 if (input_connect_to_the_left == -3)
14187 output_connect_to_the_left.push_back(-1);
14191 output_connect_to_the_left.push_back(input_connect_to_the_left);
14195 if (input_connect_to_the_right == -2)
14197 std::stringstream error_message;
14199 <<
"The connection flag to the right ("
14200 << input_connect_to_the_right <<
") indicates a connection\n"
14201 <<
"with the same polyline.\n However, only one sub-polyline was "
14202 <<
"found and no loops\nwere identified\n\n";
14204 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14205 OOMPH_EXCEPTION_LOCATION);
14210 if (input_connect_to_the_right == -3)
14212 output_connect_to_the_right.push_back(-1);
14216 output_connect_to_the_right.push_back(input_connect_to_the_right);
14224 unsigned tmp_shd_bnd_id = initial_shd_bnd_id;
14232 Node* left_sub_node_pt = tmp_sub_nodes[0].front();
14233 Node* right_sub_node_pt = tmp_sub_nodes[0].back();
14236 if (left_sub_node_pt == right_sub_node_pt)
14242 std::list<Node*> first_half_node_pt;
14243 std::list<Node*> second_half_node_pt;
14255 const unsigned n_sub_nodes = tmp_sub_nodes[0].size();
14259 const unsigned n_sub_nodes_half =
static_cast<unsigned>(n_sub_nodes / 2.0);
14264 std::list<Node*>::iterator it_sub = tmp_sub_nodes[0].begin();
14267 first_half_node_pt.push_back(*it_sub);
14273 unsigned counter_nodes = 0;
14274 unsigned counter2 = 0;
14277 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14280 first_half_node_pt.push_back(*it_sub);
14283 first_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14285 first_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14287 first_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14295 if (counter_nodes == n_sub_nodes_half)
14306 second_half_node_pt.push_back(*it_sub);
14312 for (;it_sub != tmp_sub_nodes[0].end(); it_sub++)
14315 second_half_node_pt.push_back(*it_sub);
14318 second_half_ele_pt.push_back(tmp_sub_bnd_ele_pt[0][counter2]);
14320 second_half_ele_face_pt.push_back(tmp_sub_bnd_face_ele_pt[0][counter2]);
14322 second_half_face_idx.push_back(tmp_sub_face_idx_ele[0][counter2]);
14330 output_sorted_nodes_pt.push_back(first_half_node_pt);
14331 output_sorted_nodes_pt.push_back(second_half_node_pt);
14334 output_boundary_element_pt.push_back(first_half_ele_pt);
14335 output_boundary_element_pt.push_back(second_half_ele_pt);
14338 output_boundary_face_element_pt.push_back(first_half_ele_face_pt);
14339 output_boundary_face_element_pt.push_back(second_half_ele_face_pt);
14342 output_face_index_element.push_back(first_half_face_idx);
14343 output_face_index_element.push_back(second_half_face_idx);
14354 if (input_connect_to_the_left == -3)
14357 output_connect_to_the_left.push_back(-1);
14360 else if (input_connect_to_the_left == -2)
14363 output_connect_to_the_left.push_back(-1);
14368 output_connect_to_the_left.push_back(input_connect_to_the_left);
14374 output_connect_to_the_right.push_back(-1);
14385 output_connect_to_the_left.push_back(tmp_shd_bnd_id-1);
14391 if (n_sub_list == 1)
14393 if (input_connect_to_the_right == -3)
14396 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14398 else if (input_connect_to_the_right == -2)
14401 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14403 else if (input_connect_to_the_right == -1)
14406 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14411 output_connect_to_the_right.push_back(input_connect_to_the_right);
14417 output_connect_to_the_right.push_back(tmp_shd_bnd_id-1);
14427 std::stringstream error_message;
14429 <<
"The initial and final node in the current shared polyline are not\n"
14430 <<
"the same and the number of sublists is ("<< n_sub_list <<
").\n"
14431 <<
"We can not handle more than one sublist in the method to break\n"
14432 <<
"loops at the load balance stage\n\n";
14434 "TriangleMesh::break_loops_on_shared_polyline_load_balance_helper()",
14435 OOMPH_EXCEPTION_LOCATION);
14446 template<
class ELEMENT>
14449 const unsigned &shd_bnd_id,
14450 const unsigned &iproc,
14451 const unsigned &jproc,
14452 std::list<Node*> &sorted_nodes,
14453 const int &root_edge_bnd_id,
14457 &unsorted_polylines_pt,
14458 const int &connect_to_the_left_flag,
14459 const int &connect_to_the_right_flag)
14470 Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
14473 Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
14478 processors[0] = iproc;
14479 processors[1] = jproc;
14480 Shared_boundary_from_processors[shd_bnd_id] = processors;
14486 if (iproc == my_rank || jproc == my_rank)
14493 const unsigned n_nodes = sorted_nodes.size();
14498 unsigned counter = 0;
14500 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14501 it != sorted_nodes.end(); it++)
14503 vertices[counter].resize(2);
14504 vertices[counter][0] = (*it)->x(0);
14505 vertices[counter][1] = (*it)->x(1);
14521 if (root_edge_bnd_id != -1)
14525 Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
14526 static_cast<unsigned>(root_edge_bnd_id);
14534 const unsigned n_shared_boundary_elements = bulk_bnd_ele_pt.size();
14538 const unsigned n_face_index = face_index_ele.size();
14539 if (n_shared_boundary_elements != n_face_index)
14541 std::ostringstream error_message;
14543 <<
"The number of shared boundary elements is different from the\n"
14544 <<
"number of face indexes associated to the shared boundary\n"
14546 <<
"Number of shared boundary elements: ("
14547 << n_shared_boundary_elements <<
")\n"
14548 <<
"Number of face indexes: (" << n_face_index <<
")\n\n";
14550 "TriangleMesh::create_shared_polyline()",
14551 OOMPH_EXCEPTION_LOCATION);
14557 for (
unsigned i = 0 ;
i < n_shared_boundary_elements;
i++)
14559 add_shared_boundary_element(shd_bnd_id, bulk_bnd_ele_pt[
i]);
14560 add_face_index_at_shared_boundary(shd_bnd_id, face_index_ele[
i]);
14564 for (std::list<Node*>::iterator it = sorted_nodes.begin();
14565 it != sorted_nodes.end(); it++)
14567 add_shared_boundary_node(shd_bnd_id, (*it));
14575 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
14580 const unsigned n_procs = unsorted_polylines_pt.size();
14585 unsorted_polylines_pt[iproc].push_back(polyline_pt);
14589 unsorted_polylines_pt[jproc].push_back(polyline_pt);
14595 unsorted_polylines_pt[0].push_back(polyline_pt);
14599 this->Free_curve_section_pt.insert(polyline_pt);
14609 if (connect_to_the_left_flag < 0)
14612 if (connect_to_the_left_flag != -1)
14614 std::ostringstream error_message;
14616 <<
"The only accepted values for the connection flags are:\n"
14617 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14618 <<
"check that you previously called the methods to deal with\n"
14619 <<
"other flag values\n"
14620 <<
"The current flag value for connection to the left is: ("
14621 << connect_to_the_left_flag<<
")\n\n";
14623 "TriangleMesh::create_shared_polyline()",
14624 OOMPH_EXCEPTION_LOCATION);
14629 if (connect_to_the_right_flag < 0)
14632 if (connect_to_the_right_flag != -1)
14634 std::ostringstream error_message;
14636 <<
"The only accepted values for the connection flags are:\n"
14637 <<
"POSITIVE values or -1, any other value is rejected, please\n"
14638 <<
"check that you previously called the methods to deal with\n"
14639 <<
"other flag values\n"
14640 <<
"The current flag value for connection to the right is: ("
14641 << connect_to_the_right_flag<<
")\n\n";
14643 "TriangleMesh::create_shared_polyline()",
14644 OOMPH_EXCEPTION_LOCATION);
14650 if (connect_to_the_left_flag != -1)
14653 const unsigned bnd_id_connection_to_the_left =
14654 static_cast<unsigned>(connect_to_the_left_flag);
14659 bnd_id_connection_to_the_left;
14666 if (connect_to_the_right_flag != -1)
14669 const unsigned bnd_id_connection_to_the_right =
14670 static_cast<unsigned>(connect_to_the_right_flag);
14675 bnd_id_connection_to_the_right;
14689 template <
class ELEMENT>
14693 &ntmp_boundary_elements_in_region,
14697 const unsigned nbound = this->nboundary();
14700 const unsigned n_regions = this->nregion();
14703 for (
unsigned b = 0; b < nbound; b++)
14708 const unsigned nbound_ele = this->nboundary_element(b);
14711 Vector<int> backed_up_face_index_at_boundary(nbound_ele);
14712 for (
unsigned e = 0;
e < nbound_ele;
e++)
14715 backed_up_boundary_element_pt[
e] = this->boundary_element_pt(b,
e);
14717 backed_up_face_index_at_boundary[
e] =
14718 this->face_index_at_boundary(b,
e);
14723 backed_up_boundary_region_element_pt(n_regions);
14728 for (
unsigned ir = 0; ir < n_regions; ir++)
14731 const unsigned region_id =
14732 static_cast<unsigned>(this->region_attribute(ir));
14734 const unsigned nbnd_region_ele =
14735 this->nboundary_element_in_region(b, region_id);
14738 for (
unsigned e = 0;
e < nbnd_region_ele;
e++)
14741 backed_up_boundary_region_element_pt[ir][
e] =
14742 this->boundary_element_in_region_pt(b, region_id,
e);
14745 backed_up_face_index_at_boundary_region[ir][
e] =
14746 this->face_index_at_boundary_in_region(b, region_id,
e);
14752 this->Boundary_element_pt[b].clear();
14753 this->Face_index_at_boundary[b].clear();
14756 this->Boundary_region_element_pt[b].clear();
14757 this->Face_index_region_at_boundary[b].clear();
14766 const unsigned nold_bnd_ele = ntmp_boundary_elements[b];
14768 for (
unsigned e = 0;
e < nold_bnd_ele;
e++)
14773 std::find(deleted_elements.begin(),
14774 deleted_elements.end(),
14778 if (it == deleted_elements.end())
14781 this->Boundary_element_pt[b].push_back(add_ele_pt);
14782 const int face_index = backed_up_face_index_at_boundary[
e];
14783 this->Face_index_at_boundary[b].push_back(face_index);
14791 for (
unsigned ir = 0; ir < n_regions; ir++)
14794 const unsigned region_id =
14795 static_cast<unsigned>(this->region_attribute(ir));
14798 const unsigned nold_bnd_region_ele =
14799 ntmp_boundary_elements_in_region[b][ir];
14803 for (
unsigned e = 0;
e < nold_bnd_region_ele;
e++)
14807 backed_up_boundary_region_element_pt[ir][
e];
14810 std::find(deleted_elements.begin(),
14811 deleted_elements.end(),
14815 if (it == deleted_elements.end())
14818 backed_up_boundary_region_element_pt[ir][
e];
14819 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14820 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
14821 this->Face_index_region_at_boundary[b][region_id].
14822 push_back(face_index);
14834 for (
unsigned e = nold_bnd_ele;
e < nbound_ele;
e++)
14837 this->Boundary_element_pt[b].push_back(add_ele_pt);
14838 const int face_index = backed_up_face_index_at_boundary[
e];
14839 this->Face_index_at_boundary[b].push_back(face_index);
14845 for (
unsigned ir = 0; ir < n_regions; ir++)
14848 const unsigned region_id =
14849 static_cast<unsigned>(this->region_attribute(ir));
14852 const unsigned nold_bnd_region_ele =
14853 ntmp_boundary_elements_in_region[b][ir];
14856 const unsigned nbnd_region_ele =
14857 this->nboundary_element_in_region(b, region_id);
14861 for (
unsigned e = nold_bnd_region_ele;
e < nbnd_region_ele;
e++)
14863 FiniteElement* add_ele_pt = backed_up_boundary_region_element_pt[ir][
e];
14864 this->Boundary_region_element_pt[b][region_id].push_back(add_ele_pt);
14865 const int face_index = backed_up_face_index_at_boundary_region[ir][
e];
14866 this->Face_index_region_at_boundary[b][region_id].push_back(face_index);
14874 Lookup_for_elements_next_boundary_is_setup=
true;
14878 #endif // OOMPH_HAS_MPI
14880 #ifdef OOMPH_HAS_TRIANGLE_LIB
14885 template <
class ELEMENT>
14905 (
double *) malloc(triangulate_io.
numberofpoints * 2 *
sizeof(
double));
14918 for(
unsigned count_point=0;count_point<n_points*2;count_point++)
14920 triangle_refine.
pointlist[count_point]=
14925 if (count_point%2==0)
14927 x_coord[count_point/2] = triangulate_io.
pointlist[count_point];
14931 y_coord[(count_point-1)/2] = triangulate_io.
pointlist[count_point];
14936 for(
unsigned count_marker=0;count_marker<n_points;count_marker++)
14943 for(
unsigned count_seg=0;count_seg<n_segments*2;count_seg++)
14950 for(
unsigned count_markers=0;count_markers<n_segments;count_markers++)
14961 (
double*) malloc(triangulate_io.
numberofholes * 2 *
sizeof(
double));
14964 for(
unsigned count_hole=0;count_hole<n_holes*2;count_hole++)
14966 triangle_refine.
holelist[count_hole] = triangulate_io.
holelist[count_hole];
14974 if (n_triangles!=target_area.size())
14976 std::stringstream err;
14977 err <<
"Number of triangles in triangulate_io="
14978 << n_triangles <<
" doesn't match\n"
14979 <<
"size of target area vector ("
14980 << target_area.size() <<
")\n";
14983 OOMPH_CURRENT_FUNCTION,
14984 OOMPH_EXCEPTION_LOCATION);
14995 for(
unsigned count_tri=0;count_tri<n_triangles*3;count_tri++)
15004 for(
unsigned count_area=0;count_area<n_triangles;count_area++)
15017 for(
unsigned count_attribute=0;
15027 #ifdef OOMPH_HAS_MPI
15042 const std::pair<double, double> &rhs)
const
15044 double diff_y=lhs.second-rhs.second;
15055 double diff_x=lhs.first-rhs.first;
15056 if (fabs(diff_x)<
Tol)
15058 std::ostringstream warning_message;
15060 <<
"Dodgy \"lower left\" (lexicographic) comparison "
15061 <<
"of points with cooordinates: "
15062 <<
" lhs = ( " << lhs.first <<
" , " << lhs.second <<
" ) \n"
15063 <<
" rhs = ( " << rhs.first <<
" , " << rhs.second <<
" ) \n"
15064 <<
"x and y coordinates differ by less than tolerance!\n"
15065 <<
"diff_x = " << diff_x <<
"\n"
15066 <<
"diff_y = " << diff_y <<
"\n"
15067 <<
"Tol = " <<
Tol <<
"\n";
15069 OOMPH_CURRENT_FUNCTION,
15070 OOMPH_EXCEPTION_LOCATION);
15073 if (lhs.first < rhs.first)
15130 template <
class ELEMENT>
15135 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
15138 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
15141 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
15146 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
15153 double min_distance_squared=DBL_MAX;
15158 const unsigned b = my_rank_shared_boundaries_ids[
i];
15161 const unsigned nbnd_node = this->nshared_boundary_node(b);
15165 for (
unsigned i_node = 0; i_node < nbnd_node; i_node++)
15167 Node* node_pt = this->shared_boundary_node_pt(b, i_node);
15168 std::pair<double, double> vertex = std::make_pair(node_pt->
x(0),
15170 sorted_nodes_pt[vertex] = node_pt;
15177 for (
unsigned j_node = 0; j_node < nbnd_node; j_node++)
15179 if (i_node!=j_node)
15181 Node* node2_pt = this->shared_boundary_node_pt(b, j_node);
15184 double squared_distance=0.0;
15185 for (
unsigned ii=0;ii<2;ii++)
15188 (node_pt->
x(ii)-node2_pt->
x(ii))*
15189 (node_pt->
x(ii)-node2_pt->
x(ii));
15191 if (squared_distance<min_distance_squared)
15193 min_distance_squared=squared_distance;
15200 std::ostringstream warning_message;
15202 <<
"Minimum distance between nodes on boundary " << b <<
"\n"
15203 <<
"is " << sqrt(min_distance_squared) <<
" which is less than "
15205 <<
"This may screw up the ordering of the nodes on shared boundaries\n";
15207 OOMPH_CURRENT_FUNCTION,
15208 OOMPH_EXCEPTION_LOCATION);
15215 unsigned counter = 0;
15217 this->Sorted_shared_boundary_node_pt[b].resize(nbnd_node);
15223 for (std::map<std::pair<double, double>,
Node*>::iterator it_map
15224 = sorted_nodes_pt.begin(); it_map != sorted_nodes_pt.end(); it_map++)
15227 this->Sorted_shared_boundary_node_pt[b][counter++] = (*it_map).second;
15239 template <
class ELEMENT>
15242 const bool update_elements,
15243 const bool flush_nodes,
15244 const bool update_nodes)
15247 const unsigned my_rank = this->communicator_pt()->my_rank();
15253 const unsigned initial_id = this->initial_shared_boundary_id();
15256 const unsigned final_id = this->final_shared_boundary_id();
15258 if (flush_elements)
15261 this->flush_shared_boundary_element();
15263 this->flush_face_index_at_shared_boundary();
15269 this->flush_shared_boundary_node();
15272 for (
unsigned b = initial_id; b < final_id; b++)
15276 procs_from_shrd_bnd = this->shared_boundary_from_processors(b);
15277 bool current_processor_has_b_boundary =
false;
15278 const unsigned n_procs_from_shrd_bnd = procs_from_shrd_bnd.size();
15279 for (
unsigned p = 0; p < n_procs_from_shrd_bnd; p++)
15281 if (procs_from_shrd_bnd[p] == my_rank)
15283 current_processor_has_b_boundary =
true;
15288 if (current_processor_has_b_boundary)
15290 if (update_elements)
15292 const unsigned nboundary_ele = this->nboundary_element(b);
15293 for (
unsigned e = 0;
e < nboundary_ele;
e++)
15298 this->add_shared_boundary_element(b, bnd_ele_pt);
15300 int face_index = this->face_index_at_boundary(b,
e);
15301 this->add_face_index_at_shared_boundary(b, face_index);
15309 const unsigned nboundary_node = this->nboundary_node(b);
15310 for (
unsigned n = 0;
n < nboundary_node;
n++)
15312 Node* bnd_node_pt = this->boundary_node_pt(b,
n);
15313 this->add_shared_boundary_node(b, bnd_node_pt);
15326 template <
class ELEMENT>
15330 unsigned nproc = this->communicator_pt()->nproc();
15332 unsigned my_rank = this->communicator_pt()->my_rank();
15335 double tt_start = 0.0;
15350 other_proc_shd_bnd_node_pt(nproc);
15352 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15355 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
15356 for (
unsigned jproc = 0; jproc < nproc; jproc++)
15359 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
15360 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
15361 const unsigned nshared_bound = final_shd_bnd_id - initial_shd_bnd_id;
15362 other_proc_shd_bnd_node_pt[iproc][jproc].resize(nshared_bound);
15375 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
15382 double t_start_global_node_names_and_shared_nodes =
15388 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
15390 node_name_to_global_index,
15391 global_shared_node_pt);
15394 const unsigned n_ele = this->nelement();
15396 if (Print_timings_level_adaptation>1)
15400 double t_final_global_node_names_and_shared_nodes =
15402 oomph_info <<
"CPU for computing global node names and shared nodes "
15403 <<
"[n_ele="<< n_ele <<
"]: "
15404 << t_final_global_node_names_and_shared_nodes << std::endl;
15421 double t_start_send_info_shd_nodes_on_original_bnds =
15426 send_boundary_node_info_of_shared_nodes(global_node_names,
15427 node_name_to_global_index,
15428 global_shared_node_pt);
15430 if (Print_timings_level_adaptation>1)
15435 <<
"CPU for sending info. of shared nodes on original boundaries: "
15464 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15466 const unsigned n_shd_bnd_iproc = this->nshared_boundaries(my_rank, iproc);
15467 ele_with_node_on_shd_bnd_pt[iproc].resize(n_shd_bnd_iproc);
15474 for (
unsigned e = 0;
e < n_ele;
e++)
15479 const unsigned n_nodes = ele_pt->
nnode();
15482 for (
unsigned n = 0;
n < n_nodes;
n++)
15491 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15496 const unsigned n_shd_bnd_iproc =
15497 this->nshared_boundaries(my_rank, iproc);
15500 if (iproc != my_rank && n_shd_bnd_iproc > 0)
15505 this->shared_boundaries_ids(my_rank, iproc);
15508 for (
unsigned isb = 0; isb < n_shd_bnd_iproc; isb++)
15510 const unsigned shd_bnd_id = shd_bnd_ids[isb];
15511 const unsigned n_ele_shd_bnd =
15512 this->nshared_boundary_element(shd_bnd_id);
15516 if (n_ele_shd_bnd > 0 &&
15517 this->is_node_on_shared_boundary(shd_bnd_id, node_pt))
15521 ele_with_node_on_shd_bnd_pt[iproc][isb].push_back(ele_pt);
15564 double t_start_regenerate_halo_ed_elements_nodes_first_stage =
15568 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15571 if (iproc != my_rank)
15574 const unsigned nshared_boundaries_with_iproc =
15575 this->nshared_boundaries(my_rank, iproc);
15577 if (nshared_boundaries_with_iproc > 0)
15591 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15597 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank, iproc);
15600 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15602 const unsigned bnd_id = bound_shared_with_iproc[bs];
15604 const unsigned nel_bnd = this->nshared_boundary_element(bnd_id);
15615 std::map<FiniteElement*,bool> already_added;
15618 for (
unsigned e = 0;
e < nel_bnd;
e++)
15622 this->shared_boundary_element_pt(bnd_id,
e);
15627 if (!already_added[ele_pt])
15630 haloed_element.push_back(ele_pt);
15632 already_added[ele_pt] =
true;
15643 const unsigned n_ele_with_node_on_shd_bnd =
15644 ele_with_node_on_shd_bnd_pt[iproc][bs].size();
15647 for (
unsigned iele = 0; iele < n_ele_with_node_on_shd_bnd; iele++)
15651 ele_with_node_on_shd_bnd_pt[iproc][bs][iele];
15653 if (!already_added[ele_pt])
15656 haloed_element.push_back(ele_pt);
15658 already_added[ele_pt] =
true;
15666 const unsigned nhaloed_ele = haloed_element.size();
15674 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15675 std::stringstream junk;
15676 junk <<
"Number of haloed elements " << nhaloed_ele;
15681 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15685 const unsigned nroot_haloed_ele =
15686 this->nroot_haloed_element(iproc);
15691 const unsigned haloed_ele_index =
15692 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
15696 if (nroot_haloed_ele == haloed_ele_index)
15699 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15704 get_required_elemental_information_helper(iproc, ele_pt);
15707 const unsigned nnodes = ele_pt->
nnode();
15708 for (
unsigned j = 0; j < nnodes; j++)
15714 add_haloed_node_helper(iproc, node_pt);
15721 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15725 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15740 int send_proc =
static_cast<int>(iproc);
15742 int recv_proc =
static_cast<int>(iproc);
15743 send_and_receive_elements_nodes_info(send_proc, recv_proc);
15756 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
15759 const unsigned nhaloed_ele =
15762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15764 <<
" Number of elements need to be constructed "
15770 for (
unsigned e = 0;
e < nhaloed_ele;
e++)
15774 create_halo_element(iproc,
15775 iproc_currently_created_nodes_pt[iproc],
15776 other_proc_shd_bnd_node_pt,
15778 node_name_to_global_index,
15779 global_shared_node_pt);
15791 if (Print_timings_level_adaptation>1)
15794 double t_final_regenerate_halo_ed_elements_nodes_first_stage =
15797 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15798 <<
"(first stage) [n_ele="<< n_ele <<
"]: "
15799 << t_final_regenerate_halo_ed_elements_nodes_first_stage
15816 double t_start_regenerate_halo_ed_elements_nodes_second_stage =
15821 reset_halo_haloed_scheme_helper(other_proc_shd_bnd_node_pt,
15822 iproc_currently_created_nodes_pt,
15824 node_name_to_global_index,
15825 global_shared_node_pt);
15827 if (Print_timings_level_adaptation>1)
15830 double t_final_regenerate_halo_ed_elements_nodes_second_stage =
15833 oomph_info <<
"CPU for re-generating halo(ed) elements/nodes "
15834 <<
"(second stage) [n_ele="<< n_ele <<
"]: "
15835 << t_final_regenerate_halo_ed_elements_nodes_second_stage
15847 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
15853 if (Print_timings_level_adaptation>1)
15857 <<
"CPU for resetting halo-haloed scheme (without classification of halo and haloed nodes): "
15858 << tt_end-tt_start << std::endl;
15864 const bool report_stats =
true;
15869 this->classify_halo_and_haloed_nodes(tmp_doc_info,report_stats);
15873 if (Print_timings_level_adaptation>1)
15877 <<
"CPU for resetting halo-haloed scheme (with classification of halo and haloed nodes): "
15878 << tt_end-tt_start << std::endl;
15896 template <
class ELEMENT>
15900 &other_proc_shd_bnd_node_pt,
15906 const unsigned nproc = this->communicator_pt()->nproc();
15908 const unsigned my_rank = this->communicator_pt()->my_rank();
15920 unsigned counter_nodes = 0;
15922 std::map<Node*, bool> done_node;
15924 std::map<Node*, unsigned> local_node_number;
15945 for (
unsigned iproc = 0; iproc < nproc; iproc++)
15948 if (iproc != my_rank)
15951 const unsigned n_shd_bnds_with_iproc =
15952 this->nshared_boundaries(my_rank, iproc);
15956 this->shared_boundaries_ids(my_rank, iproc);
15959 for (
unsigned ishd = 0; ishd < n_shd_bnds_with_iproc; ishd++)
15962 std::map<Node*,bool> done_node_shd_bnd;
15964 unsigned shd_bnd_id = bnd_shd_with_iproc[ishd];
15966 const unsigned n_shd_bnd_ele =
15967 this->nshared_boundary_element(shd_bnd_id);
15970 for (
unsigned e = 0;
e < n_shd_bnd_ele;
e++)
15974 this->shared_boundary_element_pt(shd_bnd_id,
e);
15977 const unsigned n_nodes = ele_pt->
nnode();
15980 for (
unsigned n = 0;
n < n_nodes;
n++)
15988 if (!done_node_shd_bnd[node_pt] &&
15989 this->is_node_on_shared_boundary(shd_bnd_id,
15993 done_node_shd_bnd[node_pt] =
true;
15998 const unsigned n_nodes_shd_bnd =
15999 nsorted_shared_boundary_node(shd_bnd_id);
16002 unsigned index = 0;
16006 bool found_node_on_shared_boundary =
false;
16010 for (
unsigned k = 0; k < n_nodes_shd_bnd; k++)
16013 Node* shd_bnd_node_pt =
16014 sorted_shared_boundary_node_pt(shd_bnd_id, k);
16017 if (shd_bnd_node_pt == node_pt)
16023 found_node_on_shared_boundary =
true;
16032 if (!found_node_on_shared_boundary)
16034 std::ostringstream error_message;
16036 <<
"The index of the node on boundary ("<<shd_bnd_id
16037 <<
") was not found.\n"
16038 <<
"These are the node coordinates\n"
16039 <<
"("<<node_pt->
x(0)<<
","<<node_pt->
x(1)<<
").\n";
16041 OOMPH_CURRENT_FUNCTION,
16042 OOMPH_EXCEPTION_LOCATION);
16048 node_name[0] = my_rank;
16049 node_name[1] = iproc;
16050 node_name[2] = shd_bnd_id;
16051 node_name[3] = index;
16056 if (!done_node[node_pt])
16061 local_node_pt.push_back(node_pt);
16064 local_node_number[node_pt] = counter_nodes;
16066 node_name[4] = counter_nodes;
16070 done_node[node_pt] =
true;
16075 first_node_name[0] = node_name;
16076 local_node_names.push_back(first_node_name);
16083 unsigned node_number = local_node_number[node_pt];
16086 node_name[4] = node_number;
16090 local_node_names[node_number].push_back(node_name);
16116 unsigned n_total_local_names = 0;
16118 const unsigned n_local_nodes = local_node_names.size();
16121 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16124 const unsigned n_inode_names = local_node_names[
i].size();
16126 n_total_local_names+=n_inode_names;
16131 const unsigned n_info_per_node_name = 5;
16133 Vector<unsigned> flat_packed_send_udata(n_total_local_names*n_info_per_node_name);
16135 unsigned counter = 0;
16137 for (
unsigned i = 0;
i < n_local_nodes;
i++)
16140 const unsigned n_inode_names = local_node_names[
i].size();
16142 for (
unsigned j = 0 ; j < n_inode_names; j++)
16145 flat_packed_send_udata[counter++]=local_node_names[
i][j][0];
16147 flat_packed_send_udata[counter++]=local_node_names[
i][j][1];
16149 flat_packed_send_udata[counter++]=local_node_names[
i][j][2];
16151 flat_packed_send_udata[counter++]=local_node_names[
i][j][3];
16153 flat_packed_send_udata[counter++]=local_node_names[
i][j][4];
16163 const unsigned n_udata_send_to_root = flat_packed_send_udata.size();
16176 const unsigned root_processor = 0;
16184 MPI_Gather(&n_total_local_names, 1, MPI_UNSIGNED,
16185 &root_n_names_per_processor[0], 1, MPI_UNSIGNED,
16186 root_processor, comm_pt->mpi_comm());
16190 unsigned root_n_total_udata_receive = 0;
16192 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16194 root_n_udata_to_receive[iproc]=
16195 root_n_names_per_processor[iproc]*n_info_per_node_name;
16196 root_n_total_udata_receive+=root_n_udata_to_receive[iproc];
16202 root_uoffsets_receive[0] = 0;
16203 for (
unsigned iproc = 1; iproc < nproc; iproc++)
16206 root_uoffsets_receive[iproc] =
16207 root_uoffsets_receive[iproc-1] + root_n_udata_to_receive[iproc-1];
16212 if (flat_packed_send_udata.size()==0)
16214 flat_packed_send_udata.resize(1);
16218 Vector<unsigned> root_flat_packed_receive_udata(root_n_total_udata_receive);
16221 if (my_rank!=root_processor)
16224 if (root_flat_packed_receive_udata.size()==0)
16226 root_flat_packed_receive_udata.resize(1);
16231 MPI_Gatherv(&flat_packed_send_udata[0],
16234 n_udata_send_to_root,
16237 &root_flat_packed_receive_udata[0],
16241 &root_n_udata_to_receive[0],
16244 &root_uoffsets_receive[0],
16250 comm_pt->mpi_comm());
16253 flat_packed_send_udata.clear();
16254 flat_packed_send_udata.resize(0);
16268 if (my_rank == root_processor)
16283 unsigned rcounter = 0;
16285 for (
unsigned iproc = 0; iproc < nproc; iproc++)
16288 const unsigned n_local_names_iproc =
16289 root_n_names_per_processor[iproc];
16290 for (
unsigned i = 0;
i < n_local_names_iproc;
i++)
16294 for (
unsigned j = 0; j < n_info_per_node_name; j++)
16295 {node_name[j] = root_flat_packed_receive_udata[rcounter++];}
16298 root_local_node_names.push_back(node_name);
16305 const unsigned n_root_local_node_names =
16306 root_local_node_names.size();
16321 std::map<Vector<unsigned>,
bool> done_name;
16325 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16331 if (!done_name[node_name])
16334 done_name[node_name] =
true;
16338 bool found_both_names_node =
false;
16343 for (
unsigned j =
i+1; j < n_root_local_node_names; j++)
16348 if (!done_name[node_name_r])
16352 if (node_name[0] == node_name_r[1] &&
16353 node_name[1] == node_name_r[0] &&
16354 node_name[2] == node_name_r[2] &&
16355 node_name[3] == node_name_r[3])
16358 done_name[node_name_r] =
true;
16361 node_name_counter_part[
i] = j;
16364 node_name_counter_part[j] =
i;
16367 found_both_names_node =
true;
16379 if (!found_both_names_node)
16381 std::ostringstream error_message;
16383 <<
"The counter-part of the current name node was "
16384 <<
"not found,\nthe current node name is:\n"
16385 <<
"iproc:("<<node_name[0]<<
")\n"
16386 <<
"jproc:("<<node_name[1]<<
")\n"
16387 <<
"ishd_bnd:("<<node_name[2]<<
")\n"
16388 <<
"index:("<<node_name[3]<<
")\n";
16390 OOMPH_CURRENT_FUNCTION,
16391 OOMPH_EXCEPTION_LOCATION);
16407 for (
unsigned i = 0;
i < n_root_local_node_names;
i++)
16413 if (!done_name[node_name])
16419 all_node_names.push_back(node_name);
16422 unsigned idx_c = node_name_counter_part[
i];
16427 all_node_names.push_back(node_name_r);
16433 unsigned n_current_names = all_node_names.size();
16436 unsigned icounter = 0;
16439 while(icounter < n_current_names)
16447 if (!done_name[current_node_name])
16450 done_name[current_node_name] =
true;
16455 for (
unsigned j=
i+1;j<n_root_local_node_names;j++)
16461 if (!done_name[other_node_name])
16464 if ((current_node_name[0] == other_node_name[0]) &&
16465 (current_node_name[4] == other_node_name[4]))
16470 done_name[other_node_name] =
true;
16474 = std::find(all_node_names.begin(),
16475 all_node_names.end(),
16477 if (it==all_node_names.end())
16479 all_node_names.push_back(other_node_name);
16481 unsigned k = node_name_counter_part[j];
16484 root_local_node_names[k];
16488 if (!done_name[other_node_name_r])
16490 all_node_names.push_back(other_node_name_r);
16505 n_current_names = all_node_names.size();
16513 root_global_node_names.push_back(all_node_names);
16526 flat_packed_root_send_receive_udata.clear();
16528 const unsigned n_global_nodes = root_global_node_names.size();
16531 flat_packed_root_send_receive_udata.push_back(n_global_nodes);
16534 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16538 root_global_node_names[
i];
16540 const unsigned n_names_global_inode = global_inode_names.size();
16543 flat_packed_root_send_receive_udata.push_back(n_names_global_inode);
16545 for (
unsigned j = 0; j < n_names_global_inode; j++)
16548 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16552 flat_packed_root_send_receive_udata.
16553 push_back(global_inode_names[j][k]);
16574 unsigned root_n_udata_sent_to_all_proc =
16575 flat_packed_root_send_receive_udata.size();
16577 MPI_Bcast(&root_n_udata_sent_to_all_proc,
16579 1, MPI_UNSIGNED, root_processor,
16580 comm_pt->mpi_comm());
16583 if (my_rank != root_processor)
16585 flat_packed_root_send_receive_udata.
16586 resize(root_n_udata_sent_to_all_proc);
16590 MPI_Bcast(&flat_packed_root_send_receive_udata[0],
16594 root_n_udata_sent_to_all_proc,
16599 comm_pt->mpi_comm());
16604 const unsigned n_global_nodes =
16605 flat_packed_root_send_receive_udata[counter++];
16612 global_node_names.resize(n_global_nodes);
16614 unsigned n_read_global_nodes = 0;
16615 while (n_read_global_nodes < n_global_nodes)
16618 const unsigned n_names_global_inode =
16619 flat_packed_root_send_receive_udata[counter++];
16621 const unsigned i = n_read_global_nodes;
16623 global_node_names[
i].resize(n_names_global_inode);
16625 for (
unsigned j = 0; j < n_names_global_inode; j++)
16628 global_node_names[
i][j].resize(n_info_per_node_name);
16631 for (
unsigned k = 0; k < n_info_per_node_name; k++)
16635 global_node_names[
i][j][k] =
16636 flat_packed_root_send_receive_udata[counter++];
16643 node_name[0] = global_node_names[
i][j][0];
16644 node_name[1] = global_node_names[
i][j][1];
16645 node_name[2] = global_node_names[
i][j][2];
16646 node_name[3] = global_node_names[
i][j][3];
16651 node_name_to_global_index[node_name] =
i;
16656 n_read_global_nodes++;
16662 if (counter != root_n_udata_sent_to_all_proc)
16664 std::ostringstream error_stream;
16666 <<
"The info. received from root regarding the global names of "
16667 <<
"the nodes\nwas not completely read.\n"
16668 <<
"The number of data sent/received from root is: ("
16669 <<root_n_udata_sent_to_all_proc<<
")\n"
16670 <<
"The number of data read from the received info. is: ("
16671 <<counter<<
")\n\n";
16673 OOMPH_CURRENT_FUNCTION,
16674 OOMPH_EXCEPTION_LOCATION);
16692 global_shared_node_pt.resize(n_global_nodes, 0);
16695 for (
unsigned i = 0;
i < n_global_nodes;
i++)
16699 bool is_this_a_local_node_name =
false;
16700 unsigned local_node_number;
16702 const unsigned n_names_global_inode = global_node_names[
i].size();
16704 for (
unsigned j = 0; j < n_names_global_inode; j++)
16707 const unsigned iproc = global_node_names[
i][j][0];
16708 local_node_number = global_node_names[
i][j][4];
16711 if (my_rank == iproc)
16714 is_this_a_local_node_name =
true;
16723 if (is_this_a_local_node_name)
16728 const unsigned n_names_local_node =
16729 local_node_names[local_node_number].size();
16730 unsigned n_names_found_on_global_name_node = 0;
16735 global_shared_node_pt[
i] = local_node_pt[local_node_number];
16741 for (
unsigned j = 0; j < n_names_global_inode; j++)
16744 const unsigned iproc = global_node_names[
i][j][0];
16747 if (iproc != my_rank)
16750 local_node_names[local_node_number].
16751 push_back(global_node_names[
i][j]);
16756 const unsigned jproc = global_node_names[
i][j][1];
16757 const unsigned ishd_bnd = global_node_names[
i][j][2];
16758 const unsigned idx = global_node_names[
i][j][3];
16759 const unsigned n_local_node = global_node_names[
i][j][4];
16761 for (
unsigned k = 0; k < n_names_local_node; k++)
16763 if ((local_node_names[local_node_number][k][0] == iproc) &&
16764 (local_node_names[local_node_number][k][1] == jproc) &&
16765 (local_node_names[local_node_number][k][2] == ishd_bnd) &&
16766 (local_node_names[local_node_number][k][3] == idx) &&
16767 (local_node_names[local_node_number][k][4] == n_local_node))
16771 n_names_found_on_global_name_node++;
16785 if (n_names_local_node != n_names_found_on_global_name_node)
16787 std::ostringstream error_stream;
16789 <<
"The local node names corresponding to the local "
16790 <<
"node ("<< local_node_number <<
") were\n"
16791 <<
"not found on the global node names.\n\n"
16792 <<
"These are the names of the local node\n"
16793 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16794 for (
unsigned k = 0; k < n_names_local_node; k++)
16796 error_stream<<
"Name("<<k<<
"): "
16797 <<local_node_names[local_node_number][k][0]
16798 <<
", "<<local_node_names[local_node_number][k][1]
16799 <<
", "<<local_node_names[local_node_number][k][2]
16800 <<
", "<<local_node_names[local_node_number][k][3]
16801 <<
", "<<local_node_names[local_node_number][k][4]
16806 <<
"\n\nThese are the names of the global node\n"
16807 <<
"Name k: iproc, jproc, ishd_bnd, idx. #node\n";
16808 for (
unsigned k = 0; k < n_names_global_inode; k++)
16810 error_stream<<
"Name("<<k<<
"): "
16811 <<global_node_names[
i][k][0] <<
", "
16812 <<global_node_names[
i][k][1] <<
", "
16813 <<global_node_names[
i][k][2] <<
", "
16814 <<global_node_names[
i][k][3] <<
", "
16815 <<global_node_names[
i][k][4] <<
"\n";
16819 OOMPH_CURRENT_FUNCTION,
16820 OOMPH_EXCEPTION_LOCATION);
16846 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
16849 for (
unsigned i = 0 ;
i < n_local_nodes;
i++)
16852 const unsigned n_names = local_node_names[
i].size();
16856 Node* node_pt = local_node_pt[
i];
16859 for (
unsigned j = 0; j < n_names; j++)
16862 const unsigned iproc = local_node_names[
i][j][0];
16863 const unsigned jproc = local_node_names[
i][j][1];
16864 const unsigned ishd_bnd =
16865 local_node_names[
i][j][2] - initial_shd_bnd_id;
16866 const unsigned index = local_node_names[
i][j][3];
16873 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]=node_pt;
16877 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]=node_pt;
16896 template <
class ELEMENT>
16904 const unsigned nproc = this->communicator_pt()->nproc();
16905 const unsigned my_rank = this->communicator_pt()->my_rank();
16908 const unsigned n_nodes_on_shd_bnds = global_node_names.size();
16919 std::map<Node*, unsigned> node_pt_to_global_shd_bnd_index;
16923 for (
unsigned i = 0;
i < n_nodes_on_shd_bnds;
i++)
16927 const unsigned n_names = global_node_names[
i].size();
16929 for (
unsigned j = 0; j < n_names; j++)
16933 node_name[0] = global_node_names[
i][j][0];
16934 node_name[1] = global_node_names[
i][j][1];
16935 node_name[2] = global_node_names[
i][j][2];
16936 node_name[3] = global_node_names[
i][j][3];
16939 if (node_name[0]==my_rank)
16942 const unsigned jproc = node_name[1];
16945 std::map<Vector<unsigned>,
unsigned>::iterator it =
16946 node_name_to_global_index.find(node_name);
16947 if (it!=node_name_to_global_index.end())
16951 if (
i!=(*it).second)
16953 std::ostringstream error_message;
16955 <<
"The global node number "<<(*it).second
16956 <<
") obtained from the current node\n"
16957 <<
"name is not the same as the current node number ("
16960 <<
"iproc:"<<node_name[0]<<
"\n"
16961 <<
"jproc:"<<node_name[1]<<
"\n"
16962 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
16963 <<
"index:"<<node_name[3]<<
"\n\n";
16965 OOMPH_CURRENT_FUNCTION,
16966 OOMPH_EXCEPTION_LOCATION);
16972 std::ostringstream error_message;
16974 <<
"The node name is not registerd as living in this processor.\n"
16976 <<
"iproc:"<<node_name[0]<<
"\n"
16977 <<
"jproc:"<<node_name[1]<<
"\n"
16978 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
16979 <<
"index:"<<node_name[3]<<
"\n\n";
16981 OOMPH_CURRENT_FUNCTION,
16982 OOMPH_EXCEPTION_LOCATION);
16985 #endif // #ifdef PARANOID
16988 Node* node_pt = global_shared_node_pt[
i];
16993 std::ostringstream error_message;
16995 <<
"There is not global shared node within this\n"
16996 <<
"global node number ("<<
i<<
"). The global shared\n"
16997 <<
"node pointer is null\n\n";
16999 OOMPH_CURRENT_FUNCTION,
17000 OOMPH_EXCEPTION_LOCATION);
17002 #endif // #ifdef PARANOID
17006 node_on_shd_bnd_pt[jproc].insert(node_pt);
17009 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17012 else if (node_name[1]==my_rank)
17015 const unsigned jproc = node_name[0];
17018 std::map<Vector<unsigned>,
unsigned>::iterator it =
17019 node_name_to_global_index.find(node_name);
17020 if (it!=node_name_to_global_index.end())
17024 if (
i!=(*it).second)
17026 std::ostringstream error_message;
17028 <<
"The global node number "<<(*it).second
17029 <<
") obtained from the current node\n"
17030 <<
"name is not the same as the current node number ("
17033 <<
"iproc:"<<node_name[0]<<
"\n"
17034 <<
"jproc:"<<node_name[1]<<
"\n"
17035 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
17036 <<
"index:"<<node_name[3]<<
"\n\n";
17038 OOMPH_CURRENT_FUNCTION,
17039 OOMPH_EXCEPTION_LOCATION);
17045 std::ostringstream error_message;
17047 <<
"The node name is not registerd as living in this processor.\n"
17049 <<
"iproc:"<<node_name[0]<<
"\n"
17050 <<
"jproc:"<<node_name[1]<<
"\n"
17051 <<
"shd_bnd_id:"<<node_name[2]<<
"\n"
17052 <<
"index:"<<node_name[3]<<
"\n\n";
17054 OOMPH_CURRENT_FUNCTION,
17055 OOMPH_EXCEPTION_LOCATION);
17058 #endif // #ifdef PARANOID
17061 Node* node_pt = global_shared_node_pt[
i];
17066 std::ostringstream error_message;
17068 <<
"There is not global shared node within this\n"
17069 <<
"global node number ("<<
i<<
"). The global shared\n"
17070 <<
"node pointer is null\n\n";
17072 OOMPH_CURRENT_FUNCTION,
17073 OOMPH_EXCEPTION_LOCATION);
17075 #endif // #ifdef PARANOID
17079 node_on_shd_bnd_pt[jproc].insert(node_pt);
17082 node_pt_to_global_shd_bnd_index[node_pt] =
i;
17109 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17112 std::set<Node*> nodes_shared_pt = node_on_shd_bnd_pt[iproc];
17115 for (std::set<Node*>::iterator it = nodes_shared_pt.begin();
17116 it!=nodes_shared_pt.end(); it++)
17119 Node* node_pt = (*it);
17126 const unsigned n_bnd=this->initial_shared_boundary_id();
17129 for (
unsigned bb = 0; bb < n_bnd; bb++)
17135 on_original_boundaries.push_back(bb);
17140 zeta_coordinate.push_back(zeta[0]);
17146 if (on_original_boundaries.size()>0)
17149 std::map<Node*,unsigned>::iterator it_index =
17150 node_pt_to_global_shd_bnd_index.find(node_pt);
17152 if (it_index==node_pt_to_global_shd_bnd_index.end())
17154 std::ostringstream error_message;
17156 <<
"We could not find the global shared node index associated\n"
17157 <<
"with the node pointer with vertices coordinates:\n"
17158 <<
"("<<node_pt->
x(0)<<
", "<<node_pt->
x(1)<<
")\n\n";
17160 OOMPH_CURRENT_FUNCTION,
17161 OOMPH_EXCEPTION_LOCATION);
17165 const unsigned global_shared_node_number = (*it_index).second;
17167 global_node_on_shared_bound[iproc].push_back(global_shared_node_number);
17169 global_node_original_boundaries[iproc].
17170 push_back(on_original_boundaries);
17172 global_node_zeta_coordinate[iproc].push_back(zeta_coordinate);
17196 MPI_Request request;
17199 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17202 const unsigned n_shd_nodes_my_rank_iproc =
17203 node_on_shd_bnd_pt[iproc].size();
17207 if (n_shd_nodes_my_rank_iproc > 0 && iproc != my_rank)
17213 flat_package_unsigned_send.push_back(n_shd_nodes_my_rank_iproc);
17216 const unsigned n_global_shared_node_on_original_boundary =
17217 global_node_on_shared_bound[iproc].size();
17221 flat_package_unsigned_send.
17222 push_back(n_global_shared_node_on_original_boundary);
17229 for (
unsigned i = 0;
i < n_global_shared_node_on_original_boundary;
i++)
17232 const unsigned global_shared_node_index =
17233 global_node_on_shared_bound[iproc][
i];
17237 flat_package_unsigned_send.push_back(global_shared_node_index);
17241 global_node_original_boundaries[iproc][
i];
17245 global_node_zeta_coordinate[iproc][
i];
17249 const unsigned n_original_boundaries =
17250 on_original_boundaries.size();
17254 flat_package_unsigned_send.push_back(n_original_boundaries);
17258 for (
unsigned j = 0; j < n_original_boundaries; j++)
17262 flat_package_unsigned_send.push_back(on_original_boundaries[j]);
17264 flat_package_double_send.push_back(zeta_coordinate[j]);
17272 const unsigned n_udata_send = flat_package_unsigned_send.size();
17273 int n_udata_send_int = n_udata_send;
17276 MPI_Isend(&n_udata_send_int,1,MPI_UNSIGNED,
17277 iproc,1,comm_pt->mpi_comm(), &request);
17279 int n_udata_received_int = 0;
17280 MPI_Recv(&n_udata_received_int,1,MPI_UNSIGNED,
17281 iproc,1,comm_pt->mpi_comm(),&status);
17282 MPI_Wait(&request,MPI_STATUS_IGNORE);
17284 if (n_udata_send!=0)
17286 MPI_Isend(&flat_package_unsigned_send[0],
17287 n_udata_send,MPI_UNSIGNED,
17288 iproc,2,comm_pt->mpi_comm(),&request);
17291 const unsigned n_udata_received =
17292 static_cast<unsigned>(n_udata_received_int);
17297 if (n_udata_received!=0)
17299 MPI_Recv(&flat_package_unsigned_receive[0],
17300 n_udata_received,MPI_UNSIGNED,
17301 iproc,2,comm_pt->mpi_comm(),&status);
17304 if (n_udata_send!=0)
17306 MPI_Wait(&request,MPI_STATUS_IGNORE);
17312 const unsigned n_ddata_send = flat_package_double_send.size();
17313 int n_ddata_send_int = n_ddata_send;
17316 MPI_Isend(&n_ddata_send_int,1,MPI_UNSIGNED,
17317 iproc,1,comm_pt->mpi_comm(), &request);
17319 int n_ddata_received_int = 0;
17320 MPI_Recv(&n_ddata_received_int,1,MPI_UNSIGNED,
17321 iproc,1,comm_pt->mpi_comm(),&status);
17322 MPI_Wait(&request,MPI_STATUS_IGNORE);
17324 if (n_ddata_send!=0)
17326 MPI_Isend(&flat_package_double_send[0],
17327 n_ddata_send,MPI_DOUBLE,
17328 iproc,2,comm_pt->mpi_comm(),&request);
17331 const unsigned n_ddata_received =
17332 static_cast<unsigned>(n_ddata_received_int);
17337 if (n_ddata_received!=0)
17339 MPI_Recv(&flat_package_double_receive[0],
17340 n_ddata_received,MPI_DOUBLE,
17341 iproc,2,comm_pt->mpi_comm(),&status);
17344 if (n_ddata_send!=0)
17346 MPI_Wait(&request,MPI_STATUS_IGNORE);
17354 unsigned n_shared_nodes_received = flat_package_unsigned_receive[0];
17358 n_shared_nodes_received++;
17359 n_shared_nodes_received--;
17362 if (n_shd_nodes_my_rank_iproc != n_shared_nodes_received)
17364 std::ostringstream error_message;
17366 <<
"The number of shared nodes between the pair of processors is\n"
17368 <<
"N.shared nodes proc ("<<my_rank<<
") with proc ("<<iproc<<
"): ("
17369 <<n_shd_nodes_my_rank_iproc<<
"\n"
17370 <<
"N.shared nodes proc ("<<iproc<<
") with proc ("<<my_rank<<
"): ("
17371 <<n_shared_nodes_received<<
"\n\n"
17372 <<
"You should have got the same error in proc: ("<<iproc<<
")\n\n";
17374 OOMPH_CURRENT_FUNCTION,
17375 OOMPH_EXCEPTION_LOCATION);
17388 unsigned current_index_data = 2;
17389 unsigned current_index_ddata = 0;
17390 while(current_index_data < n_udata_received)
17393 const unsigned global_shared_node_index =
17394 flat_package_unsigned_receive[current_index_data++];
17401 const unsigned n_original_boundaries =
17402 flat_package_unsigned_receive[current_index_data++];
17405 node_pt = global_shared_node_pt[global_shared_node_index];
17409 std::ostringstream error_message;
17411 <<
"The global shared node ("<<global_shared_node_index<<
") "
17412 <<
"could not be found in this processor!!!\n"
17413 <<
"However, it was found in processor ("<<iproc<<
"). The "
17414 <<
"data may be no synchronised,\ntherefore "
17415 <<
"we may be looking for a global shared node number that "
17416 <<
"do not\ncorrespond with the one that was sent by "
17417 <<
"processor ("<<iproc<<
")\n\n";
17419 OOMPH_CURRENT_FUNCTION,
17420 OOMPH_EXCEPTION_LOCATION);
17422 #endif // #ifdef PARANOID
17426 for (
unsigned i = 0;
i < n_original_boundaries;
i++)
17430 const unsigned original_bound_id =
17431 flat_package_unsigned_receive[current_index_data++];
17434 this->add_boundary_node(original_bound_id, node_pt);
17438 zeta[0] = flat_package_double_receive[current_index_ddata++];
17462 template <
class ELEMENT>
17465 &other_proc_shd_bnd_node_pt,
17472 const unsigned nproc = this->communicator_pt()->nproc();
17473 const unsigned my_rank = this->communicator_pt()->my_rank();
17481 std::map<Node*, bool> is_global_shared_node;
17482 std::map<Node*, unsigned> global_shared_node_index;
17485 const unsigned n_global_shared_nodes = global_shared_node_pt.size();
17487 for (
unsigned i = 0;
i < n_global_shared_nodes;
i++)
17490 Node* node_pt = global_shared_node_pt[
i];
17492 is_global_shared_node[node_pt] =
true;
17494 global_shared_node_index[node_pt] =
i;
17517 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17519 if (iproc!=my_rank)
17523 this->root_haloed_element_pt(iproc);
17526 const unsigned n_haloed_ele =
17527 this->nroot_haloed_element(iproc);
17530 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17537 const unsigned n_nodes = ele_pt->
nnode();
17539 for (
unsigned n = 0;
n < n_nodes;
n++)
17544 if (is_global_shared_node[node_pt])
17547 const unsigned global_index = global_shared_node_index[node_pt];
17550 global_node_names[global_index];
17553 const unsigned n_names = iglobal_names.size();
17557 for (
unsigned j = 0; j < n_names; j++)
17561 const unsigned proc1 = iglobal_names[j][0];
17562 const unsigned proc2 = iglobal_names[j][1];
17565 additional_elements_pt[proc1].insert(gele_pt);
17566 additional_elements_pt[proc2].insert(gele_pt);
17589 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17591 if (iproc!=my_rank)
17595 std::set<GeneralisedElement*> iproc_ele_pt =
17596 additional_elements_pt[iproc];
17599 for (std::set<GeneralisedElement*>::iterator it =
17600 iproc_ele_pt.begin(); it!=iproc_ele_pt.end(); it++)
17607 this->root_haloed_element_pt(iproc);
17610 const unsigned n_haloed_ele = this->nroot_haloed_element(iproc);
17614 bool send_ele_to_iproc_processor =
true;
17619 for (
unsigned ihd = 0; ihd < n_haloed_ele; ihd++)
17623 if (gele_pt == ghd_ele_pt)
17626 send_ele_to_iproc_processor =
false;
17635 if (send_ele_to_iproc_processor)
17641 send_haloed_ele_pt[iproc].push_back(ele_pt);
17663 for (
unsigned iproc = 0; iproc < nproc; iproc++)
17666 if (iproc != my_rank)
17669 const unsigned n_additional_haloed_ele =
17670 send_haloed_ele_pt[iproc].size();
17675 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17683 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17684 std::stringstream junk;
17685 junk <<
"Number of haloed elements " << nhaloed_ele;
17690 for (
unsigned e = 0;
e < n_additional_haloed_ele;
e++)
17694 const unsigned nroot_haloed_ele =
17695 this->nroot_haloed_element(iproc);
17703 const unsigned haloed_ele_index =
17704 this->try_to_add_root_haloed_element_pt(iproc, gen_ele_pt);
17708 if (nroot_haloed_ele == haloed_ele_index)
17711 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17716 get_required_elemental_information_helper(iproc, ele_pt);
17719 const unsigned nnodes = ele_pt->
nnode();
17720 for (
unsigned j = 0; j < nnodes; j++)
17726 add_haloed_node_helper(iproc, node_pt);
17734 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17738 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17749 int send_proc =
static_cast<int>(iproc);
17751 int recv_proc =
static_cast<int>(iproc);
17752 send_and_receive_elements_nodes_info(send_proc, recv_proc);
17759 const unsigned n_additional_halo_ele =
17762 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17764 <<
" Number of elements need to be constructed "
17770 for (
unsigned e = 0;
e < n_additional_halo_ele;
e++)
17774 create_halo_element(iproc,
17775 iproc_currently_created_nodes_pt[iproc],
17776 other_proc_shd_bnd_node_pt,
17778 node_name_to_global_index,
17779 global_shared_node_pt);
17798 template<
class ELEMENT>
17804 const unsigned nbound = this->initial_shared_boundary_id();
17812 unsigned counter_face_indexes = 0;
17814 for (
unsigned b = 0; b < nbound; b++)
17817 const unsigned nboundary_ele = nboundary_element(b);
17818 for (
unsigned e = 0;
e < nboundary_ele;
e++)
17820 if (ele_pt == this->boundary_element_pt(b,
e))
17823 associated_boundaries.push_back(b);
17825 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
17826 counter_face_indexes++;
17828 if (counter_face_indexes > 2)
17830 std::stringstream error_message;
17832 <<
"A triangular element can not have more than two of its faces "
17833 <<
"on a boundary!!!\n\n";
17835 OOMPH_CURRENT_FUNCTION,
17836 OOMPH_EXCEPTION_LOCATION);
17840 if (counter_face_indexes==2) {
break;}
17841 #endif // #ifdef PARANOID
17851 const unsigned nassociated_boundaries = associated_boundaries.size();
17852 if (nassociated_boundaries > 0)
17855 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17859 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17860 std::stringstream junk;
17861 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
17869 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
17871 unsigned b = associated_boundaries[
i];
17873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17874 std::stringstream junk;
17875 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
17878 unsigned f = face_index_on_boundary[
i];
17880 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17881 std::stringstream junk2;
17882 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
17897 const unsigned n_regions = this->nregion();
17902 unsigned counter_face_indexes_in_regions = 0;
17904 for (
unsigned b = 0; b < nbound; b++)
17907 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
17910 const unsigned region_id =
17911 static_cast<unsigned>(this->Region_attribute[i_reg]);
17916 const unsigned nele_in_region =
17917 this->nboundary_element_in_region(b, region_id);
17918 for (
unsigned ee = 0; ee < nele_in_region; ee++)
17923 this->boundary_element_in_region_pt(b, region_id, ee))
17930 bound_and_region[0] = b;
17932 bound_and_region[1] = region_id;
17935 associated_boundaries_and_regions.push_back(bound_and_region);
17937 face_index_on_boundary_and_region.push_back(
17938 this->face_index_at_boundary_in_region(b,region_id,ee));
17942 counter_face_indexes_in_regions++;
17945 if (counter_face_indexes_in_regions > 2)
17947 std::stringstream error_message;
17949 <<
"A triangular element can not have more than two of its\n"
17950 <<
"faces on a boundary!!!\n\n";
17952 OOMPH_CURRENT_FUNCTION,
17953 OOMPH_EXCEPTION_LOCATION);
17968 const unsigned nassociated_boundaries_and_regions =
17969 associated_boundaries_and_regions.size();
17970 if (nassociated_boundaries_and_regions > 0)
17973 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17978 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17979 std::stringstream junk;
17980 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
17988 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
17990 const unsigned b = associated_boundaries_and_regions[
i][0];
17992 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
17993 std::stringstream junk;
17994 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
17998 const unsigned r = associated_boundaries_and_regions[
i][1];
18000 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18001 std::stringstream junk2;
18002 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
18006 const unsigned f = face_index_on_boundary_and_region[
i];
18008 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18009 std::stringstream junk3;
18010 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
18018 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18027 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18042 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
18045 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
18047 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
18050 const unsigned sb = my_rank_shared_boundaries_ids[
i];
18053 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
18054 for (
unsigned e = 0;
e < nboundary_ele;
e++)
18056 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
18059 associated_shared_boundaries.push_back(sb);
18061 face_index_on_shared_boundary.push_back(
18062 this->face_index_at_shared_boundary(sb,
e));
18069 const unsigned nassociated_shared_boundaries =
18070 associated_shared_boundaries.size();
18071 if (nassociated_shared_boundaries > 0)
18074 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18078 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18079 std::stringstream junk;
18080 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
18085 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
18087 const unsigned b = associated_shared_boundaries[
i];
18089 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18090 std::stringstream junk;
18091 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
18095 const unsigned f = face_index_on_shared_boundary[
i];
18097 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18098 std::stringstream junk2;
18099 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
18107 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18119 template<
class ELEMENT>
18124 unsigned my_rank = this->communicator_pt()->my_rank();
18125 const unsigned nproc = this->communicator_pt()->nproc();
18130 unsigned n_val=nod_pt->
nvalue();
18132 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18136 unsigned n_dim=nod_pt->
ndim();
18140 if (this->Time_stepper_pt!=0)
18143 n_prev=this->Time_stepper_pt->ntstorage();
18152 const unsigned n_bnd = this->initial_shared_boundary_id();
18153 for (
unsigned bb=0;bb<n_bnd;bb++)
18158 original_boundaries.push_back(bb);
18163 const unsigned n_original_boundaries = original_boundaries.size();
18165 if (n_original_boundaries > 0)
18169 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18174 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18175 std::stringstream junk;
18176 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
18181 for (
unsigned i=0;
i<n_original_boundaries;
i++)
18184 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18185 std::stringstream junk;
18186 junk<<
"Node is on boundary "<<original_boundaries[
i]<<
" of "<< nb;
18199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18206 bool node_on_shared_boundary =
false;
18209 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
18210 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
18213 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
18215 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18217 node_on_shared_boundary =
true;
18225 if (node_on_shared_boundary)
18228 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18235 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
18238 const unsigned i_bnd =
18239 this->shared_boundaries_ids(my_rank, iproc, bb);
18241 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
18243 shd_boundaries.push_back(i_bnd);
18248 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
18251 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18252 std::stringstream junk;
18253 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
18258 for (
unsigned i=0;
i<n_shd_bnd_is_on;
i++)
18261 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18262 std::stringstream junk;
18263 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
18270 unsigned shared_boundary_id = shd_boundaries[0];
18272 const unsigned n_nodes_on_shared_boundary =
18273 nsorted_shared_boundary_node(shared_boundary_id);
18275 unsigned index_node_on_shared_boundary;
18278 bool found_index_node_on_shared_boundary =
false;
18281 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
18284 Node* shared_node_pt =
18285 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
18287 if (shared_node_pt == nod_pt)
18290 index_node_on_shared_boundary =
i;
18293 found_index_node_on_shared_boundary =
true;
18301 if (!found_index_node_on_shared_boundary)
18303 std::ostringstream error_message;
18305 <<
"The index of the node on boundary ("
18306 <<shared_boundary_id<<
") was not found.\n"
18307 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
","
18308 <<nod_pt->
x(1)<<
").\n";
18310 error_message.str(),
18311 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18312 OOMPH_EXCEPTION_LOCATION);
18317 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18318 std::stringstream junk2;
18319 junk2 <<
"Node index on boundary "<<
boundaries[0]<<
" is "
18320 <<index_node_on_shared_boundary;
18329 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18345 bool node_on_shared_boundary_with_other_processors =
false;
18347 unsigned nshared_boundaries_with_other_processors_have_node = 0;
18351 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18355 if (jproc != iproc)
18358 const unsigned n_jshd_bnd =
18359 this->nshared_boundaries(my_rank, jproc);
18361 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
18364 const unsigned j_shd_bnd =
18365 this->shared_boundaries_ids(my_rank, jproc, bb);
18367 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18375 node_on_shared_boundary_with_other_processors =
true;
18378 nshared_boundaries_with_other_processors_have_node++;
18389 if (node_on_shared_boundary_with_other_processors)
18392 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18400 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18401 std::stringstream junk;
18402 junk <<
"Number of other shared boundaries that the node is on: "
18403 << nshared_boundaries_with_other_processors_have_node;
18408 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
18418 for (
unsigned jproc = 0; jproc < nproc; jproc++)
18422 if (jproc != iproc)
18426 const unsigned n_jshd_bnd =
18427 this->nshared_boundaries(my_rank, jproc);
18428 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
18431 const unsigned j_shd_bnd =
18432 this->shared_boundaries_ids(my_rank, jproc, bb);
18434 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
18437 other_processor_1.push_back(my_rank);
18439 other_processor_2.push_back(jproc);
18441 shd_bnd_ids.push_back(j_shd_bnd);
18444 counter_shd_bnd_with_other_procs_have_node++;
18455 const unsigned n_other_processors = other_processor_1.size();
18457 for (
unsigned i = 0;
i < n_other_processors;
i++)
18460 unsigned shd_bnd_id = shd_bnd_ids[
i];
18462 const unsigned n_nodes_on_shd_bnd =
18463 nsorted_shared_boundary_node(shd_bnd_id);
18466 bool found_index_node_on_shared_boundary =
false;
18468 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
18471 Node* shared_node_pt =
18472 sorted_shared_boundary_node_pt(shd_bnd_id,
i);
18474 if (shared_node_pt == nod_pt)
18480 indexes.push_back(
i);
18483 found_index_node_on_shared_boundary =
true;
18491 if (!found_index_node_on_shared_boundary)
18493 std::ostringstream error_message;
18495 <<
"The index of the node on boundary ("
18496 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n"
18497 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
","
18498 <<nod_pt->
x(1)<<
").\n";
18500 error_message.str(),
18501 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18502 OOMPH_EXCEPTION_LOCATION);
18511 if (counter_shd_bnd_with_other_procs_have_node !=
18512 nshared_boundaries_with_other_processors_have_node)
18514 std::ostringstream error_message;
18516 <<
"The number of shared boundaries where the node is on "
18517 <<
"is different:\n"
18518 <<
"nshared_boundaries_with_other_processors_have_node: ("
18519 << nshared_boundaries_with_other_processors_have_node
18521 <<
"counter_shd_bnd_with_other_procs_have_node: ("
18522 << counter_shd_bnd_with_other_procs_have_node
18525 error_message.str(),
18526 "RefineableTriangleMesh::get_required_nodal_information_helper()",
18527 OOMPH_EXCEPTION_LOCATION);
18533 for (
unsigned i = 0;
i < n_other_processors;
i++)
18536 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18537 std::stringstream junk1;
18538 junk1 <<
"Processor where the other shared boundary "
18539 <<
"has the node: " << other_processor_1[
i];
18544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18545 std::stringstream junk2;
18546 junk2 <<
"Processor where the other shared boundary "
18547 <<
"has the node: " << other_processor_2[
i];
18552 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18553 std::stringstream junk3;
18554 junk3 <<
"Other shared boundary id where the node is on"
18560 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18561 std::stringstream junk4;
18562 junk4 <<
"Node index on other shared boundary "
18574 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18583 if (!node_on_shared_boundary)
18599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18604 unsigned n_ref_val=alg_nod_pt->
nref_value();
18606 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18609 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
18617 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18620 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
18628 unsigned found_geom_object=0;
18629 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
18633 found_geom_object=i_list;
18637 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18645 if (solid_nod_pt!=0)
18648 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
18650 for (
unsigned t=0;
t<n_prev;
t++)
18659 const unsigned nvalues_solid_node = values_solid_node.size();
18661 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18662 std::stringstream junk;
18663 junk <<
"Number of values solid node: "
18664 << nvalues_solid_node;
18667 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
18674 for (
unsigned i_val=0;i_val<n_val;i_val++)
18676 for (
unsigned t=0;
t<n_prev;
t++)
18683 for (
unsigned idim=0;idim<n_dim;idim++)
18685 for (
unsigned t=0;
t<n_prev;
t++)
18698 template<
class ELEMENT>
18703 const unsigned n_haloed_nod = this->nhaloed_node(iproc);
18704 const unsigned haloed_node_index =
18705 this->try_to_add_haloed_node_pt(iproc,nod_pt);
18708 if (haloed_node_index==n_haloed_nod)
18712 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18713 std::stringstream junk;
18714 junk <<
"Node needs to be constructed [size="
18728 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18729 std::stringstream junk;
18730 junk <<
"Node was already added [size="
18740 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18751 template<
class ELEMENT>
18760 MPI_Request request;
18769 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
18770 send_proc,1,comm_pt->mpi_comm(),&request);
18772 int receive_count_double_values=0;
18773 MPI_Recv(&receive_count_double_values,1,MPI_INT,
18774 recv_proc,1,comm_pt->mpi_comm(),&status);
18775 MPI_Wait(&request,MPI_STATUS_IGNORE);
18777 if (send_count_double_values!=0)
18780 send_proc,2,comm_pt->mpi_comm(),&request);
18782 if (receive_count_double_values!=0)
18784 received_double_values.resize(receive_count_double_values);
18785 MPI_Recv(&received_double_values[0],receive_count_double_values,
18786 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
18788 if (send_count_double_values!=0)
18790 MPI_Wait(&request,MPI_STATUS_IGNORE);
18796 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18799 if (send_count_unsigned_string != send_count_unsigned_values)
18801 std::ostringstream error_message;
18803 <<
"The number of unsigned values to send to processor ("
18804 << send_proc <<
") is different from the\nnumber of annotated strings "
18805 <<
"for the communication\n\n";
18807 OOMPH_CURRENT_FUNCTION,
18808 OOMPH_EXCEPTION_LOCATION);
18810 #endif // #ifdef PARANOID
18812 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
18813 send_proc,14,comm_pt->mpi_comm(),&request);
18815 int receive_count_unsigned_values=0;
18816 MPI_Recv(&receive_count_unsigned_values,1,MPI_INT,recv_proc,14,
18817 comm_pt->mpi_comm(),&status);
18819 MPI_Wait(&request,MPI_STATUS_IGNORE);
18821 if (send_count_unsigned_values!=0)
18824 MPI_UNSIGNED,send_proc,15,comm_pt->mpi_comm(),&request);
18825 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18826 for (
unsigned i=0;
i<send_count_unsigned_values;
i++)
18828 oomph_info <<
"Sent:" <<
i <<
" to orig_proc:" << send_proc
18834 if (receive_count_unsigned_values!=0)
18836 received_unsigned_values.resize(receive_count_unsigned_values);
18837 MPI_Recv(&received_unsigned_values[0],receive_count_unsigned_values,
18838 MPI_UNSIGNED,recv_proc,15,comm_pt->mpi_comm(),&status);
18841 if (send_count_unsigned_values!=0)
18843 MPI_Wait(&request,MPI_STATUS_IGNORE);
18853 for (
int ii=0;ii<receive_count_double_values;ii++)
18858 for (
int ii=0;ii<receive_count_unsigned_values;ii++)
18869 template<
class ELEMENT>
18874 &other_proc_shd_bnd_node_pt,
18876 &global_node_names,
18878 &node_name_to_global_index,
18881 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18883 <<
" Bool: New element needs to be constructed "
18895 this->add_element_pt(new_el_pt);
18898 this->add_root_halo_element_pt(iproc, new_el_pt);
18904 this->add_halo_element_helper(iproc,f_el_pt);
18907 unsigned n_node=f_el_pt->
nnode();
18909 for (
unsigned j=0;j<n_node;j++)
18911 Node* new_nod_pt=0;
18914 add_halo_node_helper(new_nod_pt,
18915 new_nodes_on_domain,
18916 other_proc_shd_bnd_node_pt,
18919 node_name_to_global_index,
18920 global_shared_node_pt);
18927 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18930 <<
" Index of existing halo element "
18935 unsigned halo_ele_index=
18940 dynamic_cast<FiniteElement*
>(this->root_halo_element_pt(iproc,
18946 throw OomphLibError(
"Halo element is not a FiniteElement\n",
18947 OOMPH_CURRENT_FUNCTION,
18948 OOMPH_EXCEPTION_LOCATION);
18961 template<
class ELEMENT>
18965 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18967 <<
" Bool: Element is associated to an original boundary "
18974 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18977 <<
" How many boundaries are associated with the element "
18981 const unsigned nassociated_boundaries =
18984 for (
unsigned b = 0; b < nassociated_boundaries; b++)
18986 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18989 <<
" Boundary associated to the element "
18993 const unsigned bnd =
18996 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
18999 <<
" Face index of the element "
19003 const unsigned face_index =
19008 this->Boundary_element_pt[bnd].push_back(ele_pt);
19009 this->Face_index_at_boundary[bnd].push_back(face_index);
19014 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19016 <<
" Bool: Element is associated to a boundary-region "
19023 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19026 <<
" How many boundaries-regions are associated with the element "
19030 const unsigned nassociated_boundaries_and_regions =
19033 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
19035 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19038 <<
" Boundary associated to the element "
19042 const unsigned bnd =
19045 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19048 <<
" Region associated to the element "
19052 const unsigned region =
19055 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19058 <<
" Face index of the element in boundary-region "
19062 const unsigned face_index =
19067 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
19068 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
19077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19079 <<
" Bool: Element is associated to a shared boundary "
19085 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19088 <<
" How many shared boundaries are associated with the element "
19092 const unsigned nassociated_shared_boundaries =
19095 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
19097 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19100 <<
" Shared boundary associated to the element "
19104 const unsigned bnd =
19107 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19110 <<
" Face index of the element associated to the shared boundary "
19115 const unsigned face_index =
19118 this->add_shared_boundary_element(bnd, ele_pt);
19119 this->add_face_index_at_shared_boundary(bnd, face_index);
19130 template<
class ELEMENT>
19135 &other_proc_shd_bnd_node_pt,
19137 unsigned& node_index,
19145 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19147 <<
" Bool: New node needs to be constructed "
19155 construct_new_halo_node_helper(new_nod_pt, new_nodes_on_domain,
19156 other_proc_shd_bnd_node_pt,
19157 iproc, node_index, new_el_pt,
19159 node_name_to_global_index,
19160 global_shared_node_pt);
19164 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19166 <<
" Index of existing halo node "
19172 new_nod_pt = new_nodes_on_domain[
19175 new_el_pt->
node_pt(node_index)=new_nod_pt;
19185 template<
class ELEMENT>
19190 &other_proc_shd_bnd_node_pt,
19191 unsigned& iproc,
unsigned& node_index,
19199 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19201 <<
" Number of values of external halo node "
19208 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
19210 unsigned n_prev=time_stepper_pt->
ntstorage();
19214 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19216 <<
" Is the node on an original boundary "
19222 const unsigned node_on_original_boundaries =
19230 unsigned n_original_boundaries_node_is_on = 0;
19232 if (node_on_original_boundaries==2)
19235 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19237 <<
" Number of boundaries the node is on: "
19241 n_original_boundaries_node_is_on =
19245 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
19246 zeta_coordinates.resize(n_original_boundaries_node_is_on);
19248 for (
unsigned i=0;
i<n_original_boundaries_node_is_on;
i++)
19251 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19253 <<
" Node is on boundary "
19257 original_boundaries_node_is_on[
i] =
19259 zeta_coordinates[
i] =
19267 if (node_on_original_boundaries != 0)
19269 std::ostringstream error_message;
19271 <<
"The current node is not on an original boundary, this should\n"
19272 <<
"be indicated by a zero flag. However, the read value for\n"
19273 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
19275 error_message.str(),
19276 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19277 OOMPH_EXCEPTION_LOCATION);
19285 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19287 <<
" Is node on shared boundary? "
19291 const unsigned is_node_on_shared_boundary =
19293 if (is_node_on_shared_boundary == 1)
19296 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19298 <<
" Number of boundaries the node is on: "
19302 const unsigned n_shd_bnd_node_is_on =
19305 for (
unsigned i=0;
i<n_shd_bnd_node_is_on;
i++)
19308 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19310 <<
" Node is on boundary "
19314 shd_bnds_node_is_on[
i] =
19319 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19321 <<
" Index of node on boundary "
19326 unsigned node_index_on_shared_boundary =
19331 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
19332 node_index_on_shared_boundary);
19338 if (is_node_on_shared_boundary != 0)
19340 std::ostringstream error_message;
19342 <<
"The current node is not on a shared boundary, this should\n"
19343 <<
"be indicated by a zero flag. However, the read value for\n"
19344 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
19346 error_message.str(),
19347 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19348 OOMPH_EXCEPTION_LOCATION);
19355 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19357 <<
" Is the node on shared boundaries with other processors "
19364 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
19374 unsigned n_shd_bnd_with_other_procs_have_node = 0;
19377 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19379 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19381 <<
" In how many shared boundaries with other "
19382 <<
"processors is the node "
19388 n_shd_bnd_with_other_procs_have_node =
19392 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
19393 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
19394 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
19395 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
19397 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19399 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19401 <<
" Processor where the other shared boundary"
19407 other_processor_1[
i] =
19410 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19412 <<
" Processor where the other shared boundary"
19418 other_processor_2[
i] =
19421 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19423 <<
" Other shared boundary id where the node is on: "
19429 other_shared_boundaries[
i] =
19432 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19434 <<
" Node index on the other shared boundary "
19449 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
19451 std::ostringstream error_message;
19453 <<
"The current node is not on a shared boundary with\n"
19454 <<
"other processors, this should be indicated by a zero flag.\n"
19455 <<
"However, the read value for that flag is ("
19456 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
19458 error_message.str(),
19459 "RefineableTriangleMesh::construct_new_halo_node_helper()",
19460 OOMPH_EXCEPTION_LOCATION);
19469 if (is_node_on_shared_boundary == 1)
19474 if (node_on_original_boundaries==2)
19480 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19482 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19485 zeta[0] = zeta_coordinates[
i];
19487 original_boundaries_node_is_on[
i],zeta);
19493 new_nodes_on_domain.push_back(new_nod_pt);
19496 new_el_pt->
node_pt(node_index) = new_nod_pt;
19506 bool found_node_in_other_shared_boundaries =
false;
19515 bool build_node_as_boundary_node =
false;
19517 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
19520 build_node_as_boundary_node =
true;
19527 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
19533 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
19544 unsigned oproc1 = other_processor_1[
i];
19545 unsigned oproc2 = other_processor_2[
i];
19546 if (other_processor_1[
i] > other_processor_2[
i])
19548 oproc1 = other_processor_2[
i];
19549 oproc2 = other_processor_1[
i];
19554 const unsigned shd_bnd_id =
19555 other_shared_boundaries[
i] - initial_shd_bnd_id;
19558 const unsigned index = other_indexes[
i];
19562 const unsigned n_nodes_on_other_processor =
19563 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
19565 if (n_nodes_on_other_processor > 0)
19569 std::map<unsigned, Node*>::iterator it =
19570 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
19575 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
19578 found_node_in_other_shared_boundaries =
true;
19580 Node* tmp_node_pt = (*it).second;
19583 found_node_pt.push_back(tmp_node_pt);
19594 if (found_node_in_other_shared_boundaries)
19597 const unsigned n_times_node_found = found_node_pt.size();
19598 for (
unsigned j = 1; j < n_times_node_found; j++)
19600 if (found_node_pt[j-1] != found_node_pt[j])
19602 std::ostringstream error_message;
19604 <<
"The instances of the node that was found on\n"
19605 <<
"shared boundaries with other processors (but not\n"
19606 <<
"on shared boundaries with this processor) are not\n"
19608 <<
"These are the coordinates of the instances of the\n"
19610 <<
"(" << found_node_pt[j-1]->x(0) <<
", "
19611 << found_node_pt[j-1]->x(1) <<
")\n"
19612 <<
"(" << found_node_pt[j]->x(0) <<
", "
19613 << found_node_pt[j]->x(1) <<
")\n"
19614 <<
"Dont be surprised if they are the same since the "
19615 <<
"node is\nrepeated.\n";
19617 OOMPH_CURRENT_FUNCTION,
19618 OOMPH_EXCEPTION_LOCATION);
19623 #endif // #ifdef PARANOID
19629 if (is_node_on_shared_boundary == 1)
19638 if (found_node_pt[0] != new_nod_pt)
19640 std::ostringstream error_message;
19642 <<
"The pointer of the node that was found to be on a\n"
19643 <<
"shared boundary with other processor(s) and the pointer\n"
19644 <<
"of the node on shared boundary with the receiver\n"
19645 <<
"processor (iproc) are not the same. This means we have a\n"
19646 <<
"repeated node)\n"
19647 <<
"The coordinates for the nodes are:\n"
19648 <<
"(" << found_node_pt[0]->x(0) <<
", "
19649 << found_node_pt[0]->x(1) <<
")\n"
19650 <<
"(" << new_nod_pt->
x(0) <<
", "
19651 << new_nod_pt->
x(1) <<
")\n"
19652 <<
"Dont be surprised if they are the same since the "
19653 <<
"node is\nrepeated.\n";
19655 OOMPH_CURRENT_FUNCTION,
19656 OOMPH_EXCEPTION_LOCATION);
19667 new_nod_pt = found_node_pt[0];
19678 if (is_node_on_shared_boundary != 1)
19692 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
19696 if (!found_node_in_other_shared_boundaries)
19699 if (time_stepper_pt!=0)
19713 new_el_pt->
node_pt(node_index) = new_nod_pt;
19718 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
19720 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
19723 zeta[0] = zeta_coordinates[
i];
19725 original_boundaries_node_is_on[
i],zeta);
19733 if (!found_node_in_other_shared_boundaries)
19736 if (time_stepper_pt!=0)
19738 new_nod_pt=new_el_pt->
construct_node(node_index, time_stepper_pt);
19748 new_el_pt->
node_pt(node_index) = new_nod_pt;
19759 new_nodes_on_domain.push_back(new_nod_pt);
19763 if (!found_node_in_other_shared_boundaries)
19766 this->add_node_pt(new_nod_pt);
19775 if (new_alg_nod_pt!=0)
19784 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19786 <<
" Alg node update id "
19798 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19800 <<
" Alg node # of ref values "
19809 ref_value.resize(n_ref_val);
19810 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
19823 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19825 <<
" Alg node # of geom objects "
19834 geom_object_pt.resize(n_geom_obj);
19835 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
19837 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19839 <<
" Alg node: geom object index "
19851 geom_object_pt[i_geom]=alg_mesh_pt->
19852 geom_object_list_pt(geom_index);
19857 if (!found_node_in_other_shared_boundaries)
19862 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
19873 if (!found_node_in_other_shared_boundaries)
19879 if (macro_nod_pt!=0)
19889 geom_object_vector_pt=
19895 (node_index,s_in_macro_node_update_element);
19899 (new_el_pt,s_in_macro_node_update_element,
19900 geom_object_vector_pt);
19906 unsigned n_new_val=new_nod_pt->
nvalue();
19910 if (!found_node_in_other_shared_boundaries)
19912 if (n_val>n_new_val)
19928 new std::map<unsigned, unsigned>;
19932 std::map<unsigned, unsigned>* map_pt=
19937 const unsigned id_face = 0;
19939 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
19942 if(p==map_pt->end())
19946 (*map_pt)[id_face] = n_new_val;
19949 new_nod_pt->
resize(n_val);
19958 if (solid_nod_pt!=0)
19961 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
19963 for (
unsigned t=0;
t<n_prev;
t++)
19970 if (!found_node_in_other_shared_boundaries)
19973 set_value(
t, i_val, read_data);
19980 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION
19982 <<
" Number of values solid node: "
19986 const unsigned nvalues_solid_node =
19989 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
19991 values_solid_node[
i] =
19997 if (!found_node_in_other_shared_boundaries)
19999 unsigned index = 0;
20007 for (
unsigned i_val=0;i_val<n_val;i_val++)
20009 for (
unsigned t=0;
t<n_prev;
t++)
20017 if (!found_node_in_other_shared_boundaries)
20027 unsigned n_dim=new_nod_pt->
ndim();
20028 for (
unsigned idim=0;idim<n_dim;idim++)
20030 for (
unsigned t=0;
t<n_prev;
t++)
20038 if (!found_node_in_other_shared_boundaries)
20041 new_nod_pt->
x(
t,idim) = read_data;
20053 if (n_shd_bnd_with_other_procs_have_node > 0 &&
20057 !found_node_in_other_shared_boundaries)
20065 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
20066 other_proc_shd_bnd_node_pt,
20069 other_shared_boundaries,
20072 node_name_to_global_index,
20073 global_shared_node_pt);
20083 template<
class ELEMENT>
20088 &other_proc_shd_bnd_node_pt,
20099 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
20104 const unsigned n_data = other_processor_1.size();
20105 #endif // #ifdef PARANOID
20109 node_name[0] = other_processor_1[0];
20110 node_name[1] = other_processor_2[0];
20111 node_name[2] = other_shared_boundaries[0];
20112 node_name[3] = other_indexes[0];
20116 std::map<Vector<unsigned>,
unsigned>::iterator it =
20117 node_name_to_global_index.find(node_name);
20118 if (it==node_name_to_global_index.end())
20120 std::ostringstream error_stream;
20122 <<
"The node name does not exist in the global node names\n"
20123 <<
"This is the name of the node\n"
20124 <<
"Name: iproc, jproc, ishd_bnd, idx\n"
20125 <<
"Name: " << node_name[0] <<
", " << node_name[1] <<
", "
20126 << node_name[2] <<
", " << node_name[3] <<
"\n";
20128 OOMPH_CURRENT_FUNCTION,
20129 OOMPH_EXCEPTION_LOCATION);
20131 #endif // #ifdef PARANOID
20134 const unsigned iglobal_node = node_name_to_global_index[node_name];
20136 global_shared_node_pt[iglobal_node] = new_node_pt;
20140 const unsigned n_names = inode_names.size();
20145 unsigned n_found_node_names_on_global_node_name = 0;
20147 for (
unsigned j = 0; j < n_data; j++)
20150 for (
unsigned k = 0; k < n_names; k++)
20153 if (inode_names[k][0] == other_processor_1[j] &&
20154 inode_names[k][1] == other_processor_2[j] &&
20155 inode_names[k][2] == other_shared_boundaries[j] &&
20156 inode_names[k][3] == other_indexes[j])
20160 n_found_node_names_on_global_node_name++;
20168 if (n_found_node_names_on_global_node_name != n_data)
20170 std::ostringstream error_stream;
20172 <<
"Not all the node names of the current node were found on the\n"
20173 <<
"global node names. This happened when adding the node pointer\n"
20174 <<
"to the data structure that keeps tracks of nodes on shared\n"
20175 <<
"boundaries with other processors\n\n"
20176 <<
"These are the names of the current node\n"
20177 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20178 for (
unsigned j = 0; j < n_data; j++)
20180 error_stream<<
"Name("<<j<<
"): "
20181 <<other_processor_1[j] <<
", "
20182 <<other_processor_2[j] <<
", "
20183 <<other_shared_boundaries[j] <<
", "
20184 <<other_indexes[j] <<
"\n";
20188 <<
"\n\nThese are the names of the global node\n"
20189 <<
"Name k: iproc, jproc, ishd_bnd, idx\n";
20190 for (
unsigned k = 0; k < n_names; k++)
20192 error_stream<<
"Name("<<k<<
"): "
20193 <<inode_names[k][0] <<
", "
20194 <<inode_names[k][1] <<
", "
20195 <<inode_names[k][2] <<
", "
20196 <<inode_names[k][3] <<
"\n";
20200 OOMPH_CURRENT_FUNCTION,
20201 OOMPH_EXCEPTION_LOCATION);
20203 #endif // #ifdef PARANOID
20206 for (
unsigned j = 0; j < n_names; j++)
20209 const unsigned iproc = inode_names[j][0];
20210 const unsigned jproc = inode_names[j][1];
20211 const unsigned ishd_bnd = inode_names[j][2] - initial_shd_bnd_id;
20212 const unsigned index = inode_names[j][3];
20218 other_proc_shd_bnd_node_pt[iproc][jproc][ishd_bnd][index]
20223 other_proc_shd_bnd_node_pt[jproc][iproc][ishd_bnd][index]
20243 template <
class ELEMENT>
20246 target_domain_for_local_non_halo_element)
20248 oomph_info <<
"Load balance (unstructured mesh) [BEGIN]" << std::endl;
20252 if (!this->is_mesh_distributed())
20254 std::ostringstream warning_message;
20256 <<
"\n===============================================================\n"
20257 <<
"The load balancing can only be performed in distributed meshes,\n"
20258 <<
"your mesh has not been distributed.\n"
20259 <<
"===============================================================\n\n";
20261 OOMPH_CURRENT_FUNCTION,
20262 OOMPH_EXCEPTION_LOCATION);
20268 const unsigned nproc = this->communicator_pt()->nproc();
20270 const unsigned my_rank = this->communicator_pt()->my_rank();
20275 std::ostringstream warning_message;
20277 <<
"\n===============================================================\n"
20278 <<
"The load balancing can only be performed when there are at least\n"
20279 <<
"two procesors, the current number of processors is one.\n"
20280 <<
"===============================================================\n\n";
20282 OOMPH_CURRENT_FUNCTION,
20283 OOMPH_EXCEPTION_LOCATION);
20289 double t_start_overall_load_balance=0.0;
20290 if (Print_timings_level_load_balance>1)
20296 const unsigned nelement_before_load_balance = this->nelement();
20301 if (nnon_halo_element() !=
20302 target_domain_for_local_non_halo_element.size())
20304 std::ostringstream error_message;
20306 <<
"The number of non halo elements in the current mesh ("
20307 << nnon_halo_element() <<
") and the number\n"
20308 <<
"of target areas for the local non halo elements ("
20309 << target_domain_for_local_non_halo_element.size()
20310 <<
") is different\n\n";
20312 OOMPH_CURRENT_FUNCTION,
20313 OOMPH_EXCEPTION_LOCATION);
20319 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20321 backed_up_ele_pt[
e] = this->finite_element_pt(
e);
20329 double tt_start_get_domains_halo_elements=0.0;
20330 if (Print_timings_level_load_balance>1)
20353 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20357 if (iproc != my_rank)
20360 const unsigned n_halo_iproc = this->nroot_halo_element(iproc);
20362 new_domains_halo_elements[iproc].resize(n_halo_iproc);
20365 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20367 new_domains_haloed_elements[iproc].resize(n_haloed_iproc);
20380 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20384 if (iproc != my_rank)
20387 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20390 for (
unsigned ihd = 0; ihd < n_haloed_iproc; ihd++)
20394 this->root_haloed_element_pt(iproc, ihd);
20397 unsigned nh_count4 = 0;
20399 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20411 if (ele_pt == haloed_ele_pt)
20414 const unsigned element_domain =
20415 target_domain_for_local_non_halo_element[nh_count4-1];
20420 new_domains_haloed_elements[iproc][ihd] = element_domain;
20423 counter_for_found_haloed_elements[iproc]++;
20444 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20448 if (iproc != my_rank)
20451 const unsigned n_haloed_iproc = this->nroot_haloed_element(iproc);
20455 if (n_haloed_iproc != counter_for_found_haloed_elements[iproc])
20457 std::ostringstream error_message;
20459 <<
"The independent counting of found haloed elements ("
20460 << counter_for_found_haloed_elements[iproc] <<
") with processor ("
20461 << iproc <<
") is not equal to the number of haloed elements ("
20462 << n_haloed_iproc <<
") with processor (" << iproc <<
")\n";
20464 OOMPH_CURRENT_FUNCTION,
20465 OOMPH_EXCEPTION_LOCATION);
20483 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20487 if (iproc != my_rank)
20490 const unsigned n_haloed_ele_iproc = this->nroot_haloed_element(iproc);
20492 nhaloed_elements_with_iproc[iproc] = n_haloed_ele_iproc;
20495 for (
unsigned i = 0;
i < n_haloed_ele_iproc;
i++)
20497 new_domains_haloed_flat_unsigned.push_back(
20498 new_domains_haloed_elements[iproc][
i]);
20506 Vector<int> offset_haloed_elements_with_iproc(nproc);
20507 offset_haloed_elements_with_iproc[0] = 0;
20508 for (
unsigned ip = 1; ip < nproc; ip++)
20511 offset_haloed_elements_with_iproc[ip] =
20512 offset_haloed_elements_with_iproc[ip-1] +
20513 nhaloed_elements_with_iproc[ip-1];
20522 unsigned counter_halo_ele_with_all_procs = 0;
20529 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20533 if (iproc != my_rank)
20536 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20538 nhalo_elements_with_iproc[iproc] = n_halo_ele_iproc;
20540 counter_halo_ele_with_all_procs+= n_halo_ele_iproc;
20546 Vector<int> offset_halo_elements_with_iproc(nproc);
20547 offset_halo_elements_with_iproc[0] = 0;
20548 for (
unsigned ip = 1; ip < nproc; ip++)
20551 offset_halo_elements_with_iproc[ip] =
20552 offset_halo_elements_with_iproc[ip-1] +
20553 nhalo_elements_with_iproc[ip-1];
20562 new_domains_halo_flat_unsigned(counter_halo_ele_with_all_procs);
20566 MPI_Alltoallv(&new_domains_haloed_flat_unsigned[0],
20567 &nhaloed_elements_with_iproc[0],
20568 &offset_haloed_elements_with_iproc[0],
20570 &new_domains_halo_flat_unsigned[0],
20571 &nhalo_elements_with_iproc[0],
20572 &offset_halo_elements_with_iproc[0],
20574 this->communicator_pt()->mpi_comm());
20580 unsigned counter_new_domains_halo_ele = 0;
20581 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20585 if (iproc != my_rank)
20588 const unsigned ntmp_halo_elements_with_iproc =
20589 nhalo_elements_with_iproc[iproc];
20592 for (
unsigned i = 0;
i < ntmp_halo_elements_with_iproc;
i++)
20596 new_domains_halo_elements[iproc][
i] =
20597 new_domains_halo_flat_unsigned[counter_new_domains_halo_ele++];
20603 if (Print_timings_level_load_balance>1)
20605 oomph_info <<
"CPU for getting domains halo elements (load balance) [1]: "
20621 double tt_start_get_fe_version_from_ge_halo_ed=0.0;
20622 if (Print_timings_level_load_balance>1)
20632 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20635 if (iproc != my_rank)
20638 const unsigned nhalo_ele_iproc = this->nroot_halo_element(iproc);
20641 this->root_halo_element_pt(iproc);
20643 f_halo_element_pt[iproc].resize(nhalo_ele_iproc);
20645 for (
unsigned ih = 0; ih < nhalo_ele_iproc; ih++)
20651 f_halo_element_pt[iproc][ih] = ele_pt;
20655 const unsigned nhaloed_ele_iproc = this->nroot_haloed_element(iproc);
20658 this->root_haloed_element_pt(iproc);
20660 f_haloed_element_pt[iproc].resize(nhaloed_ele_iproc);
20662 for (
unsigned ihd = 0; ihd < nhaloed_ele_iproc; ihd++)
20666 dynamic_cast<FiniteElement*
>(haloed_element_pt_iproc[ihd]);
20668 f_haloed_element_pt[iproc][ihd] = ele_pt;
20677 if (Print_timings_level_load_balance>1)
20679 oomph_info <<
"CPU for getting finite element versions from generalised halo(ed) elements (load balance) [2]: "
20697 double tt_start_prepare_element_to_send=0.0;
20698 if (Print_timings_level_load_balance>1)
20708 std::map<Data*,std::set<unsigned> >
20709 processors_associated_with_data_before_load_balance;
20713 unsigned nh_count3 = 0;
20714 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20722 const unsigned element_domain =
20723 target_domain_for_local_non_halo_element[nh_count3++];
20726 elements_to_send_pt[element_domain].push_back(ele_pt);
20729 const unsigned n_nodes = ele_pt->
nnode();
20731 for (
unsigned j = 0; j < n_nodes; j++)
20736 processors_associated_with_data_before_load_balance[node_pt].
20737 insert(element_domain);
20749 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20752 if (iproc != my_rank)
20755 const unsigned n_halo_ele_iproc = this->nroot_halo_element(iproc);
20758 this->root_halo_element_pt(iproc);
20760 for (
unsigned ih = 0; ih < n_halo_ele_iproc; ih++)
20763 const unsigned element_domain =
20764 new_domains_halo_elements[iproc][ih];
20771 const unsigned n_nodes = ele_pt->
nnode();
20773 for (
unsigned j = 0; j < n_nodes; j++)
20779 processors_associated_with_data_before_load_balance[node_pt].
20780 insert(element_domain);
20791 if (Print_timings_level_load_balance>1)
20793 oomph_info <<
"CPU for preparing elements to send to other processors (load balance) [3]: "
20817 double tt_start_compute_new_local_halo_elements=0.0;
20818 if (Print_timings_level_load_balance>1)
20853 for (
unsigned iproc = 0; iproc < nproc; iproc++)
20856 new_local_halo_element_pt[iproc].resize(nproc);
20864 unsigned nh_count5 = 0;
20865 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
20873 const unsigned ele_domain =
20874 target_domain_for_local_non_halo_element[nh_count5++];
20877 if (ele_domain != iproc)
20880 const unsigned nnodes = ele_pt->
nnode();
20882 for (
unsigned j = 0; j < nnodes; j++)
20887 std::set<unsigned>::iterator it =
20888 processors_associated_with_data_before_load_balance[node_pt].
20892 processors_associated_with_data_before_load_balance[node_pt].
20899 if (!new_local_halo_already_added[ele_domain][ele_pt])
20903 new_local_halo_element_pt[iproc][ele_domain].
20906 new_local_halo_already_added[ele_domain][ele_pt] =
true;
20944 for (
unsigned jproc = 0; jproc < nproc; jproc++)
20948 if (jproc != my_rank)
20951 const unsigned n_halo_ele_jproc = this->nroot_halo_element(jproc);
20954 this->root_halo_element_pt(jproc);
20957 for (
unsigned jh = 0; jh < n_halo_ele_jproc; jh++)
20960 const unsigned ele_domain = new_domains_halo_elements[jproc][jh];
20991 if (ele_domain != iproc)
20997 const unsigned nnodes = ele_pt->
nnode();
20999 for (
unsigned j = 0; j < nnodes; j++)
21006 std::set<unsigned>::iterator it =
21007 processors_associated_with_data_before_load_balance[node_pt].
21011 processors_associated_with_data_before_load_balance[node_pt].end())
21018 if (!new_local_halo_already_added[ele_domain][ele_pt])
21022 new_local_halo_element_pt[iproc][ele_domain].
21024 new_local_halo_already_added[ele_domain][ele_pt] =
true;
21053 if (Print_timings_level_load_balance>1)
21055 oomph_info <<
"CPU for computing new local halo elements (load balance) [4]: "
21075 double tt_start_compute_new_local_shd_bnd_ele=0.0;
21076 if (Print_timings_level_load_balance>1)
21084 new_local_halo_shared_boundary_element_pt(nproc);
21086 new_local_halo_shared_boundary_element_face_index(nproc);
21089 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21091 new_local_halo_shared_boundary_element_pt[iproc].resize(nproc);
21092 new_local_halo_shared_boundary_element_face_index[iproc].resize(nproc);
21100 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21106 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
21108 this->get_shared_boundary_elements_and_face_indexes(
21109 new_local_halo_element_pt[iproc][jproc],
21110 new_local_halo_element_pt[jproc][iproc],
21111 new_local_halo_shared_boundary_element_pt[iproc][jproc],
21112 new_local_halo_shared_boundary_element_face_index[iproc][jproc],
21113 new_local_halo_shared_boundary_element_pt[jproc][iproc],
21114 new_local_halo_shared_boundary_element_face_index[jproc][iproc]);
21119 if (Print_timings_level_load_balance>1)
21121 oomph_info <<
"CPU for computing new local shared boundary elements (load balance) [5]: "
21141 double tt_start_send_elements_to_other_processors=0.0;
21142 if (Print_timings_level_load_balance>1)
21150 this->sort_nodes_on_shared_boundaries();
21161 new_received_haloed_shared_boundary_element_pt(nproc);
21163 new_received_haloed_shared_boundary_element_face_index(nproc);
21169 other_proc_shd_bnd_node_pt(nproc);
21171 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21174 other_proc_shd_bnd_node_pt[iproc].resize(nproc);
21175 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21178 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
21179 const unsigned final_shd_bnd_id = this->final_shared_boundary_id();
21180 const unsigned n_shared_bound = final_shd_bnd_id - initial_shd_bnd_id;
21181 other_proc_shd_bnd_node_pt[iproc][jproc].resize(n_shared_bound);
21194 std::map<Vector<unsigned>,
unsigned> node_name_to_global_index;
21202 compute_global_node_names_and_shared_nodes(other_proc_shd_bnd_node_pt,
21204 node_name_to_global_index,
21205 global_shared_node_pt);
21211 received_old_haloed_element_pt(nproc);
21218 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21220 received_old_haloed_element_pt[iproc].resize(nproc);
21225 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21227 if (iproc != my_rank)
21241 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21246 const unsigned nelements_to_send = elements_to_send_pt[iproc].size();
21253 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21254 std::stringstream junk;
21255 junk <<
"Number of elements to send from processor " << my_rank
21256 <<
" to processor " << iproc <<
": ("
21257 << nelements_to_send <<
")";
21262 for (
unsigned e = 0;
e < nelements_to_send;
e++)
21268 const unsigned ncurrently_sent_elements =
21269 currently_sent_elements.size();
21272 const unsigned index_ele = try_to_add_element_pt_load_balance(
21273 currently_sent_elements, send_ele_pt);
21276 if (index_ele == ncurrently_sent_elements)
21279 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21284 get_required_elemental_information_load_balance_helper(
21286 f_haloed_element_pt,
21290 const unsigned nnodes = send_ele_pt->
nnode();
21293 for (
unsigned j = 0; j < nnodes; j++)
21298 add_node_load_balance_helper(iproc,
21300 currently_sent_nodes,
21309 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21313 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21333 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21339 const unsigned njproc_iproc_new_local_halo_shared_boundary_ele =
21340 new_local_halo_shared_boundary_element_pt[jproc][iproc].size();
21347 unsigned nfound_new_local_halo_shared_bound_ele_index = 0;
21350 unsigned nnon_halo_new_local_halo_shared_bound_ele = 0;
21354 for (
unsigned e = 0;
21355 e < njproc_iproc_new_local_halo_shared_boundary_ele;
e++)
21359 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21363 if (!shared_ele_pt->
is_halo())
21365 nnon_halo_new_local_halo_shared_bound_ele++;
21370 const unsigned ncurrently_sent_elements =
21371 currently_sent_elements.size();
21373 for (
unsigned ics = 0; ics < ncurrently_sent_elements; ics++)
21376 currently_sent_elements[ics];
21379 if (currently_sent_ele_pt == shared_ele_pt)
21383 new_local_halo_shared_boundary_ele_index.push_back(ics);
21386 nfound_new_local_halo_shared_bound_ele_index++;
21398 if (nfound_new_local_halo_shared_bound_ele_index !=
21399 nnon_halo_new_local_halo_shared_bound_ele)
21401 std::ostringstream error_message;
21403 <<
"Was only possible to identify ("
21404 << nfound_new_local_halo_shared_bound_ele_index <<
") of ("
21405 << nnon_halo_new_local_halo_shared_bound_ele <<
") shared "
21406 <<
"elements between\nprocessor ("<<iproc<<
") and ("<<jproc<<
") "
21407 <<
"when sending elements to processor ("<<iproc<<
")\n\n";
21409 OOMPH_CURRENT_FUNCTION,
21410 OOMPH_EXCEPTION_LOCATION);
21416 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21417 std::stringstream junk;
21418 junk <<
"Flag for synchronisation 9999";
21425 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21426 std::stringstream junk2;
21427 junk2 <<
"Number of new local halo shared boundary elements "
21428 << nnon_halo_new_local_halo_shared_bound_ele;
21434 unsigned counter_nonhalo_sent = 0;
21437 for (
unsigned e = 0;
21438 e < njproc_iproc_new_local_halo_shared_boundary_ele;
e++)
21442 new_local_halo_shared_boundary_element_pt[jproc][iproc][
e];
21446 if (!shared_ele_pt->
is_halo())
21450 const unsigned ele_index =
21451 new_local_halo_shared_boundary_ele_index[counter_nonhalo_sent++];
21453 const unsigned face_index =
21454 new_local_halo_shared_boundary_element_face_index[jproc][iproc][
e];
21459 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21460 std::stringstream junk;
21461 junk <<
"The index of the halo shared boundary element "
21469 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21470 std::stringstream junk2;
21471 junk2 <<
"The face index of the halo shared boundary element "
21486 int send_proc =
static_cast<int>(iproc);
21488 int recv_proc =
static_cast<int>(iproc);
21489 send_and_receive_elements_nodes_info(send_proc, recv_proc);
21504 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
21506 <<
" Number of elements need to be constructed "
21512 const unsigned nelements_to_create =
21515 for (
unsigned e = 0;
e < nelements_to_create;
e++)
21519 create_element_load_balance_helper(iproc,
21520 f_haloed_element_pt,
21521 received_old_haloed_element_pt,
21522 currently_created_elements,
21523 currently_created_nodes,
21524 other_proc_shd_bnd_node_pt,
21526 node_name_to_global_index,
21527 global_shared_node_pt);
21533 const unsigned nreceived_elements = currently_created_elements.size();
21534 received_elements_pt[iproc].resize(nreceived_elements);
21535 for (
unsigned e = 0;
e < nreceived_elements;
e++)
21536 {received_elements_pt[iproc][
e] = currently_created_elements[
e];}
21542 new_received_haloed_shared_boundary_element_pt[iproc].resize(nproc);
21543 new_received_haloed_shared_boundary_element_face_index[iproc].resize(nproc);
21546 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21549 const unsigned synchronisation_flag =
21552 if (synchronisation_flag != 9999)
21554 std::ostringstream error_message;
21556 <<
"The synchronisation flag was not read, the\n"
21557 <<
"information sent between processor (" << my_rank <<
") "
21558 <<
"and ("<< iproc <<
")\nis no longer synchronised\n\n";
21560 OOMPH_CURRENT_FUNCTION,
21561 OOMPH_EXCEPTION_LOCATION);
21567 const unsigned niproc_jproc_new_received_haloed_shared_boundary_ele =
21571 for (
unsigned e = 0;
21572 e < niproc_jproc_new_received_haloed_shared_boundary_ele;
e++)
21576 const unsigned ele_index =
21580 const unsigned face_index =
21585 currently_created_elements[ele_index];
21590 new_received_haloed_shared_boundary_element_pt[iproc][jproc].
21591 push_back(shared_ele_pt);
21593 new_received_haloed_shared_boundary_element_face_index[iproc][jproc].
21594 push_back(face_index);
21605 if (Print_timings_level_load_balance>1)
21607 oomph_info <<
"CPU for sending elements to their new processors (load balance) [6]: "
21627 double tt_start_compute_additional_shared_boundaries=0.0;
21628 if (Print_timings_level_load_balance>1)
21637 tmp_group1_shared_boundary_element_pt(nproc);
21639 tmp_group1_shared_boundary_element_face_index(nproc);
21641 tmp_group2_shared_boundary_element_pt(nproc);
21643 tmp_group2_shared_boundary_element_face_index(nproc);
21667 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21669 if (my_rank < iproc)
21672 this->get_shared_boundary_elements_and_face_indexes(
21673 received_elements_pt[iproc], elements_to_send_pt[iproc],
21674 tmp_group1_shared_boundary_element_pt[iproc],
21675 tmp_group1_shared_boundary_element_face_index[iproc],
21676 tmp_group2_shared_boundary_element_pt[iproc],
21677 tmp_group2_shared_boundary_element_face_index[iproc]);
21680 else if (my_rank > iproc)
21683 this->get_shared_boundary_elements_and_face_indexes(
21684 elements_to_send_pt[iproc], received_elements_pt[iproc],
21685 tmp_group1_shared_boundary_element_pt[iproc],
21686 tmp_group1_shared_boundary_element_face_index[iproc],
21687 tmp_group2_shared_boundary_element_pt[iproc],
21688 tmp_group2_shared_boundary_element_face_index[iproc]);
21695 if (Print_timings_level_load_balance>1)
21697 oomph_info <<
"CPU for computing additional shared boundaries (load balance) [7]: "
21717 double tt_start_sort_shared_boundaries=0.0;
21718 if (Print_timings_level_load_balance>1)
21743 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21746 if (my_rank < iproc)
21750 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21753 if (jproc != my_rank)
21756 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21757 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21758 for (
unsigned e = 0;
21759 e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
e++)
21763 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
21765 const unsigned face_index =
21766 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][
e];
21769 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21770 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21780 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21781 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21782 for (
unsigned e = 0;
21783 e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
e++)
21787 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
21789 const unsigned face_index =
21790 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][
e];
21798 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21799 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21806 const unsigned ntmp_group1_shared_bound_ele_iproc =
21807 tmp_group1_shared_boundary_element_pt[iproc].size();
21808 for (
unsigned e = 0;
e < ntmp_group1_shared_bound_ele_iproc;
e++)
21812 tmp_group1_shared_boundary_element_pt[iproc][
e];
21814 const unsigned face_index =
21815 tmp_group1_shared_boundary_element_face_index[iproc][
e];
21818 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21819 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21825 else if (my_rank > iproc)
21833 const unsigned nlocal_haloed_shared_bound_ele_iproc_my_rank =
21834 new_local_halo_shared_boundary_element_pt[iproc][my_rank].size();
21835 for (
unsigned e = 0;
21836 e < nlocal_haloed_shared_bound_ele_iproc_my_rank;
e++)
21840 new_local_halo_shared_boundary_element_pt[iproc][my_rank][
e];
21842 const unsigned face_index =
21843 new_local_halo_shared_boundary_element_face_index[iproc][my_rank][
e];
21851 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21852 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21857 for (
unsigned jproc = 0; jproc < nproc; jproc++)
21860 if (jproc != my_rank)
21864 const unsigned nrecvd_haloed_shared_bound_ele_jproc_iproc =
21865 new_received_haloed_shared_boundary_element_pt[jproc][iproc].size();
21866 for (
unsigned e = 0;
21867 e < nrecvd_haloed_shared_bound_ele_jproc_iproc;
e++)
21871 new_received_haloed_shared_boundary_element_pt[jproc][iproc][
e];
21873 const unsigned face_index =
21874 new_received_haloed_shared_boundary_element_face_index[jproc][iproc][
e];
21877 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21878 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21888 const unsigned ntmp_group2_shared_bound_ele_iproc =
21889 tmp_group2_shared_boundary_element_pt[iproc].size();
21890 for (
unsigned e = 0;
e < ntmp_group2_shared_bound_ele_iproc;
e++)
21894 tmp_group2_shared_boundary_element_pt[iproc][
e];
21896 const unsigned face_index =
21897 tmp_group2_shared_boundary_element_face_index[iproc][
e];
21900 new_shared_boundary_element_pt[iproc].push_back(ele_pt);
21901 new_shared_boundary_element_face_index[iproc].push_back(face_index);
21910 if (Print_timings_level_load_balance>1)
21912 oomph_info <<
"CPU for sorting shared boundaries (load balance) [8]: "
21934 double tt_start_create_new_shared_boundaries=0.0;
21935 if (Print_timings_level_load_balance>1)
21948 std::set<FiniteElement*> element_in_processor_pt;
21952 unsigned nh_count6 = 0;
21953 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
21961 if (target_domain_for_local_non_halo_element[nh_count6++] == my_rank)
21964 element_in_processor_pt.insert(ele_pt);
21974 for (
unsigned iproc = 0; iproc < nproc; iproc++)
21977 if (iproc != my_rank)
21981 const unsigned n_received_ele = received_elements_pt[iproc].size();
21982 for (
unsigned ie = 0; ie < n_received_ele; ie++)
21988 element_in_processor_pt.insert(ele_pt);
21997 create_new_shared_boundaries(element_in_processor_pt,
21998 new_shared_boundary_element_pt,
21999 new_shared_boundary_element_face_index);
22002 if (Print_timings_level_load_balance>1)
22004 oomph_info <<
"CPU for creating new shared boundaries (load balance) [9]: "
22027 double tt_start_delete_elements=0.0;
22028 if (Print_timings_level_load_balance>1)
22041 this->Halo_node_pt.clear();
22042 this->Root_halo_element_pt.clear();
22044 this->Haloed_node_pt.clear();
22045 this->Root_haloed_element_pt.clear();
22048 const unsigned nnodes = this->nnode();
22049 for (
unsigned j = 0; j < nnodes; j++)
22051 this->node_pt(j)->set_obsolete();
22055 this->flush_element_storage();
22058 this->delete_all_external_storage();
22061 this->External_halo_node_pt.clear();
22062 this->External_halo_element_pt.clear();
22064 this->External_haloed_node_pt.clear();
22065 this->External_haloed_element_pt.clear();
22071 unsigned nh_count7 = 0;
22072 for (
unsigned e = 0;
e < nelement_before_load_balance;
e++)
22078 if (target_domain_for_local_non_halo_element[nh_count7++] == my_rank)
22081 this->add_element_pt(ele_pt);
22083 const unsigned nele_nodes = ele_pt->
nnode();
22085 for (
unsigned j = 0; j < nele_nodes; j++)
22095 deleted_elements.push_back(ele_pt);
22105 deleted_elements.push_back(ele_pt);
22114 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22116 if (iproc != my_rank)
22120 const unsigned nreceived_ele = received_elements_pt[iproc].size();
22121 for (
unsigned ie = 0; ie < nreceived_ele; ie++)
22126 this->add_element_pt(ele_pt);
22128 const unsigned nele_nodes = ele_pt->
nnode();
22130 for (
unsigned j = 0; j < nele_nodes; j++)
22143 this->prune_dead_nodes();
22146 if (Print_timings_level_load_balance>1)
22148 oomph_info <<
"CPU for deleting elements no longer belonging to this processor (load balance) [10]: "
22167 double tt_start_re_etablish_halo_ed_info=0.0;
22168 if (Print_timings_level_load_balance>1)
22177 this->sort_nodes_on_shared_boundaries();
22184 const unsigned tmp_nboundary = this->nboundary();
22190 const unsigned n_regions = this->nregion();
22193 for (
unsigned ib = 0; ib < tmp_nboundary; ib++)
22196 ntmp_boundary_elements[ib] = this->nboundary_element(ib);
22199 ntmp_boundary_elements_in_region[ib].resize(n_regions);
22202 for (
unsigned rr = 0 ; rr < n_regions; rr++)
22205 const unsigned region_id =
22206 static_cast<unsigned>(this->region_attribute(rr));
22211 ntmp_boundary_elements_in_region[ib][rr] =
22212 this->nboundary_element_in_region(ib, region_id);
22219 this->reset_halo_haloed_scheme();
22222 const unsigned nelement_after_load_balance = this->nelement();
22226 this->reset_boundary_element_info(ntmp_boundary_elements,
22227 ntmp_boundary_elements_in_region,
22253 for (
unsigned b = 0; b < tmp_nboundary; b++)
22255 if (this->boundary_geom_object_pt(b)!=0)
22258 this->flush_boundary_segment_node(b);
22264 get_boundary_segment_nodes_helper(b, dummy_segment_node_pt);
22267 const unsigned nsegments = dummy_segment_node_pt.size();
22271 this->set_nboundary_segment_node(b, nsegments);
22277 if (Print_timings_level_load_balance>1)
22279 oomph_info <<
"CPU for re-establishing halo(ed) information (load balance) [11]: "
22291 if (Print_timings_level_load_balance>1)
22293 oomph_info <<
"CPU for load balance [n_ele_before="
22294 <<nelement_before_load_balance<<
", n_ele_after="
22295 <<nelement_after_load_balance<<
"]: "
22300 oomph_info <<
"Load balance (unstructured mesh) [END]" << std::endl;
22309 template <
class ELEMENT>
22325 const unsigned nfirst_element = first_element_pt.size();
22327 for (
unsigned ef = 0; ef < nfirst_element; ef++)
22332 bool first_ele_is_halo =
false;
22335 first_ele_is_halo =
true;
22338 for (
unsigned ifface = 0; ifface < 3; ifface++)
22343 first_face[0] = fele_pt->
node_pt(1);
22344 first_face[1] = fele_pt->
node_pt(2);
22346 else if (ifface == 1)
22348 first_face[0] = fele_pt->
node_pt(2);
22349 first_face[1] = fele_pt->
node_pt(0);
22351 else if (ifface == 2)
22353 first_face[0] = fele_pt->
node_pt(0);
22354 first_face[1] = fele_pt->
node_pt(1);
22361 const unsigned nsecond_element = second_element_pt.size();
22363 for (
unsigned es = 0; es < nsecond_element; es++)
22368 bool second_ele_is_halo =
false;
22371 second_ele_is_halo =
true;
22378 if (!(first_ele_is_halo && second_ele_is_halo))
22381 for (
unsigned isface = 0; isface < 3; isface++)
22386 second_face[0] = sele_pt->
node_pt(1);
22387 second_face[1] = sele_pt->
node_pt(2);
22389 else if (isface == 1)
22391 second_face[0] = sele_pt->
node_pt(2);
22392 second_face[1] = sele_pt->
node_pt(0);
22394 else if (isface == 2)
22396 second_face[0] = sele_pt->
node_pt(0);
22397 second_face[1] = sele_pt->
node_pt(1);
22402 if (first_face[0] == second_face[0] &&
22403 first_face[1] == second_face[1])
22406 first_shared_boundary_element_pt.push_back(fele_pt);
22408 first_shared_boundary_element_face_index.push_back(ifface);
22411 second_shared_boundary_element_pt.push_back(sele_pt);
22413 second_shared_boundary_element_face_index.push_back(isface);
22421 es = nsecond_element;
22425 else if (first_face[0] == second_face[1] &&
22426 first_face[1] == second_face[0])
22429 first_shared_boundary_element_pt.push_back(fele_pt);
22431 first_shared_boundary_element_face_index.push_back(ifface);
22434 second_shared_boundary_element_pt.push_back(sele_pt);
22436 second_shared_boundary_element_face_index.push_back(isface);
22444 es = nsecond_element;
22464 template <
class ELEMENT>
22467 &element_in_processor_pt,
22469 &new_shared_boundary_element_pt,
22471 &new_shared_boundary_element_face_index)
22474 const unsigned nproc = this->communicator_pt()->nproc();
22476 const unsigned my_rank = this->communicator_pt()->my_rank();
22486 double tt_start_get_edges_from_shd_bnd_face_ele=0.0;
22487 if (Print_timings_level_load_balance>2)
22502 std::map<std::pair<Node*, Node*>,
unsigned> elements_edges_on_boundary;
22505 this->get_element_edges_on_boundary(elements_edges_on_boundary);
22508 std::map<std::pair<Node*,Node*>,
bool> overlapped_edge;
22518 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22521 if (iproc != my_rank)
22525 const unsigned n_shared_bound_ele =
22526 new_shared_boundary_element_pt[iproc].size();
22533 unsigned nrepeated_faces = 0;
22537 for (
unsigned iele = 0; iele < n_shared_bound_ele; iele++)
22541 new_shared_boundary_element_pt[iproc][iele];
22545 static_cast<int>(new_shared_boundary_element_face_index[iproc][iele]);
22553 bool done_face =
false;
22557 const unsigned nnode_face_ele = tmp_ele_pt->
nnode();
22558 Node* first_face_node_pt = tmp_ele_pt->
node_pt(0);
22559 Node* last_face_node_pt = tmp_ele_pt->
node_pt(nnode_face_ele - 1);
22562 const unsigned ndone_faces = done_faces.size();
22564 for (
unsigned n = 0;
n < ndone_faces;
n++)
22566 Node* first_done_face_node_pt = done_faces[
n].first;
22567 Node* second_done_face_node_pt = done_faces[
n].second;
22568 if (first_face_node_pt == first_done_face_node_pt &&
22569 last_face_node_pt == second_done_face_node_pt)
22576 else if (first_face_node_pt == second_done_face_node_pt &&
22577 last_face_node_pt == first_done_face_node_pt)
22590 tmp_unsorted_face_ele_pt[iproc].push_back(tmp_ele_pt);
22592 tmp_unsorted_ele_pt[iproc].push_back(bulk_ele_pt);
22594 tmp_unsorted_face_index_ele[iproc].push_back(face_index);
22596 std::pair<Node*, Node*> tmp_edge =
22597 std::make_pair(first_face_node_pt, last_face_node_pt);
22599 done_faces.push_back(tmp_edge);
22603 int edge_boundary_id = -1;
22604 std::map<std::pair<Node*,Node*>,
unsigned >::iterator it;
22605 it = elements_edges_on_boundary.find(tmp_edge);
22608 if (it != elements_edges_on_boundary.end())
22612 edge_boundary_id = (*it).second;
22614 overlapped_edge[tmp_edge] =
true;
22616 std::pair<Node*, Node*> rev_tmp_edge =
22617 std::make_pair(last_face_node_pt, first_face_node_pt);
22619 overlapped_edge[rev_tmp_edge] =
true;
22624 std::pair<Node*,Node*> rtmp_edge =
22625 std::make_pair(last_face_node_pt, first_face_node_pt);
22626 it = elements_edges_on_boundary.find(rtmp_edge);
22627 if (it != elements_edges_on_boundary.end())
22631 edge_boundary_id = (*it).second;
22633 overlapped_edge[rtmp_edge] =
true;
22636 overlapped_edge[tmp_edge] =
true;
22640 tmp_edge_boundary[iproc].push_back(edge_boundary_id);
22656 if (Print_timings_level_load_balance>2)
22658 oomph_info <<
"CPU for getting edges from shared boundary face elements (load balance) [9.1]: "
22680 double tt_start_sort_shared_face_elements=0.0;
22681 if (Print_timings_level_load_balance>2)
22707 std::vector<std::vector<bool> > tmp_treat_as_inverted(nproc);
22710 std::vector<std::vector<bool> > treat_as_inverted(nproc);
22716 for (
unsigned iproc = 0; iproc < nproc; iproc++)
22719 if (iproc != my_rank)
22722 const unsigned n_face_ele = tmp_unsorted_face_ele_pt[iproc].size();
22729 tmp_treat_as_inverted[iproc].resize(n_face_ele);
22733 for (
unsigned e = 0;
e < n_face_ele;
e++)
22736 FiniteElement* face_ele_pt = tmp_unsorted_face_ele_pt[iproc][
e];
22738 const unsigned n_node = face_ele_pt->
nnode();
22743 bottom_left[0] = node_pt->
x(0);
22744 bottom_left[1] = node_pt->
x(1);
22746 tmp_treat_as_inverted[iproc][
e] =
false;
22749 for (
unsigned n = 1;
n < n_node;
n++)
22753 if (node_pt->
x(1) < bottom_left[1])
22755 bottom_left[0] = node_pt->
x(0);
22756 bottom_left[1] = node_pt->
x(1);
22759 tmp_treat_as_inverted[iproc][
e] =
true;
22761 else if (node_pt->
x(1) == bottom_left[1])
22763 if (node_pt->
x(0) < bottom_left[0])
22765 bottom_left[0] = node_pt->
x(0);
22766 bottom_left[1] = node_pt->
x(1);
22769 tmp_treat_as_inverted[iproc][
e] =
true;
22776 centroid_vertices[
e].resize(2);
22778 centroid_vertices[
e][0] =
22780 face_ele_pt->
node_pt(n_node-1)->
x(0))*0.5;
22781 centroid_vertices[
e][1] =
22783 face_ele_pt->
node_pt(n_node-1)->
x(1))*0.5;
22788 unsigned n_sorted_bottom_left = 0;
22790 std::vector<bool> done_face(n_face_ele,
false);
22793 while (n_sorted_bottom_left < n_face_ele)
22796 unsigned index = 0;
22798 for (
unsigned e = 0;
e < n_face_ele;
e++)
22804 current_bottom_left[0] = centroid_vertices[
e][0];
22805 current_bottom_left[1] = centroid_vertices[
e][1];
22815 for (
unsigned e = index + 1;
e < n_face_ele;
e++)
22820 if (centroid_vertices[
e][1] < current_bottom_left[1])
22823 current_bottom_left[0] = centroid_vertices[
e][0];
22824 current_bottom_left[1] = centroid_vertices[
e][1];
22828 else if (centroid_vertices[
e][1] == current_bottom_left[1])
22830 if (centroid_vertices[
e][0] < current_bottom_left[0])
22833 current_bottom_left[0] = centroid_vertices[
e][0];
22834 current_bottom_left[1] = centroid_vertices[
e][1];
22846 unsorted_face_ele_pt[iproc].
22847 push_back(tmp_unsorted_face_ele_pt[iproc][index]);
22849 unsorted_ele_pt[iproc].
22850 push_back(tmp_unsorted_ele_pt[iproc][index]);
22852 unsorted_face_index_ele[iproc].
22853 push_back(tmp_unsorted_face_index_ele[iproc][index]);
22855 edge_boundary[iproc].
22856 push_back(tmp_edge_boundary[iproc][index]);
22858 treat_as_inverted[iproc].
22859 push_back(tmp_treat_as_inverted[iproc][index]);
22862 done_face[index] =
true;
22865 n_sorted_bottom_left++;
22872 const unsigned tmp_n_face_ele = unsorted_face_ele_pt[iproc].size();
22874 if (tmp_n_face_ele != n_face_ele)
22876 std::ostringstream error_stream;
22878 <<
"The number of face elements before sorting them starting\n"
22879 <<
"from their bottom-left vertex is different from the number\n"
22880 <<
"of face elements after the sorting\n"
22881 <<
"N. ele before sorting: (" << n_face_ele <<
")\n"
22882 <<
"N. ele after sorting: (" << tmp_n_face_ele <<
")\n";
22884 "RefineableTriangleMesh::create_new_shared_boundaries()",
22885 OOMPH_EXCEPTION_LOCATION);
22894 if (Print_timings_level_load_balance>2)
22896 oomph_info <<
"CPU for sorting shared boundary face elements (load balance) [9.2]: "
22919 double tt_start_compute_valency_of_nodes=0.0;
22920 if (Print_timings_level_load_balance>2)
22926 std::map<Node*, unsigned> global_node_degree;
22929 compute_shared_node_degree_helper(unsorted_face_ele_pt,
22930 global_node_degree);
22933 if (Print_timings_level_load_balance>2)
22935 oomph_info <<
"CPU for computing the valency of nodes (load balance) [9.3]: "
22954 double tt_start_nodes_on_non_overlapped_shd_bnd=0.0;
22955 if (Print_timings_level_load_balance>2)
22962 std::map<unsigned, std::map<Node*, bool> >
22963 node_on_bnd_not_overlapped_by_shd_bnd;
22966 for (std::map<std::pair<Node*,Node*>,
unsigned>::iterator it_map =
22967 elements_edges_on_boundary.begin();
22968 it_map != elements_edges_on_boundary.end(); it_map++)
22971 std::pair<Node*,Node*> edge_pair = (*it_map).first;
22973 if (!overlapped_edge[edge_pair])
22977 unsigned b = (*it_map).second;
22980 Node* left_node_pt = edge_pair.first;
22981 node_on_bnd_not_overlapped_by_shd_bnd[b][left_node_pt] =
true;
22984 Node* right_node_pt = edge_pair.second;
22985 node_on_bnd_not_overlapped_by_shd_bnd[b][right_node_pt] =
true;
22993 if (Print_timings_level_load_balance>2)
22995 oomph_info <<
"CPU for computing nodes on non overlapped shared boundaries (load balance) [9.4]: "
23019 double tt_start_join_shd_bnd_face_ele=0.0;
23020 if (Print_timings_level_load_balance>2)
23052 std::map<unsigned, std::list<Node*> >
23053 local_shd_bnd_id_to_sorted_list_node_pt;
23058 unsigned local_shd_bnd_id = this->Initial_shared_boundary_id;
23063 std::map<FiniteElement*, bool> done_ele;
23066 std::map<FiniteElement*, bool> is_inverted;
23070 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23073 if (iproc != my_rank)
23077 const unsigned nunsorted_face_ele =
23078 unsorted_face_ele_pt[iproc].size();
23080 unsigned nsorted_face_ele = 0;
23083 while (nsorted_face_ele < nunsorted_face_ele)
23092 bool found_root_element =
false;
23096 unsigned root_index = 0;
23099 std::list<FiniteElement*> tmp_sorted_face_ele_pt;
23102 std::list<FiniteElement*> tmp_sorted_ele_pt;
23106 std::list<int> tmp_sorted_face_index_ele;
23111 std::list<Node*> tmp_sorted_nodes_pt;
23113 tmp_sorted_nodes_pt.clear();
23116 Node* initial_node_pt = 0;
23117 Node* final_node_pt = 0;
23121 int root_edge_bound_id = -1;
23125 for (
unsigned e = 0;
e < nunsorted_face_ele;
e++)
23130 if (!done_ele[root_ele_pt])
23134 root_edge_bound_id = edge_boundary[iproc][
e];
23137 tmp_sorted_face_ele_pt.push_back(root_ele_pt);
23139 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23142 tmp_sorted_face_index_ele.push_back(
23143 unsorted_face_index_ele[iproc][
e]);
23146 const unsigned nnodes = root_ele_pt->nnode();
23148 if (!treat_as_inverted[iproc][
e])
23150 initial_node_pt = root_ele_pt->node_pt(0);
23151 final_node_pt = root_ele_pt->node_pt(nnodes-1);
23155 initial_node_pt = root_ele_pt->node_pt(nnodes-1);
23156 final_node_pt = root_ele_pt->node_pt(0);
23159 tmp_sorted_nodes_pt.push_back(initial_node_pt);
23160 tmp_sorted_nodes_pt.push_back(final_node_pt);
23163 done_ele[root_ele_pt] =
true;
23165 if (!treat_as_inverted[iproc][
e])
23168 is_inverted[root_ele_pt] =
false;
23173 is_inverted[root_ele_pt] =
true;
23176 nsorted_face_ele++;
23181 found_root_element =
true;
23191 if (!found_root_element)
23193 std::ostringstream error_stream;
23195 <<
"It was not possible the found the root element\n\n";
23197 OOMPH_CURRENT_FUNCTION,
23198 OOMPH_EXCEPTION_LOCATION);
23206 bool new_element_added =
true;
23216 bool element_added_to_the_left =
false;
23217 bool element_added_to_the_right =
false;
23221 bool connection_to_the_left =
false;
23225 bool connection_to_the_right =
false;
23230 bool current_polyline_has_connections_at_both_ends =
false;
23242 int bound_id_connection_to_the_left = -1;
23243 int bound_id_connection_to_the_right = -1;
23247 const unsigned initial_node_degree =
23248 global_node_degree[initial_node_pt];
23252 const bool called_for_load_balance=
true;
23256 bound_id_connection_to_the_left =
23257 this->check_connections_of_polyline_nodes(
23258 element_in_processor_pt,
23259 root_edge_bound_id,
23261 node_on_bnd_not_overlapped_by_shd_bnd,
23262 tmp_sorted_nodes_pt,
23263 local_shd_bnd_id_to_sorted_list_node_pt,
23264 initial_node_degree,
23266 called_for_load_balance);
23270 if (bound_id_connection_to_the_left != -1)
23272 connection_to_the_left =
true;
23277 const unsigned final_node_degree =
23278 global_node_degree[final_node_pt];
23281 bound_id_connection_to_the_right =
23282 this->check_connections_of_polyline_nodes(
23283 element_in_processor_pt,
23284 root_edge_bound_id,
23286 node_on_bnd_not_overlapped_by_shd_bnd,
23287 tmp_sorted_nodes_pt,
23288 local_shd_bnd_id_to_sorted_list_node_pt,
23291 called_for_load_balance);
23295 if (bound_id_connection_to_the_right != -1)
23297 connection_to_the_right =
true;
23302 if (connection_to_the_left && connection_to_the_right)
23303 {current_polyline_has_connections_at_both_ends =
true;}
23311 while(new_element_added &&
23312 (nsorted_face_ele < nunsorted_face_ele)
23313 && !current_polyline_has_connections_at_both_ends)
23319 for (
unsigned e = root_index;
e < nunsorted_face_ele;
e++)
23322 new_element_added =
false;
23323 element_added_to_the_left =
false;
23324 element_added_to_the_right =
false;
23329 const int edge_bound_id = edge_boundary[iproc][
e];
23333 if (!done_ele[tmp_ele_pt]
23334 && (edge_bound_id == root_edge_bound_id))
23337 const unsigned nnodes = tmp_ele_pt->
nnode();
23340 Node* first_node_pt = 0;
23341 Node* last_node_pt = 0;
23342 if (!treat_as_inverted[iproc][
e])
23344 first_node_pt = tmp_ele_pt->
node_pt(0);
23345 last_node_pt = tmp_ele_pt->
node_pt(nnodes-1);
23349 first_node_pt = tmp_ele_pt->
node_pt(nnodes-1);
23350 last_node_pt = tmp_ele_pt->
node_pt(0);
23356 Node* new_added_node_pt = 0;
23359 if (initial_node_pt == last_node_pt &&
23360 !connection_to_the_left)
23363 new_added_node_pt = initial_node_pt = first_node_pt;
23365 tmp_sorted_nodes_pt.push_front(first_node_pt);
23368 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23370 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23373 tmp_sorted_face_index_ele.push_front(
23374 unsorted_face_index_ele[iproc][
e]);
23375 if (!treat_as_inverted[iproc][
e])
23378 is_inverted[tmp_ele_pt] =
false;
23383 is_inverted[tmp_ele_pt] =
true;
23386 new_element_added =
true;
23389 element_added_to_the_left =
true;
23392 else if (initial_node_pt == first_node_pt &&
23393 !connection_to_the_left)
23396 new_added_node_pt = initial_node_pt = last_node_pt;
23398 tmp_sorted_nodes_pt.push_front(last_node_pt);
23401 tmp_sorted_face_ele_pt.push_front(tmp_ele_pt);
23403 tmp_sorted_ele_pt.push_front(unsorted_ele_pt[iproc][
e]);
23406 tmp_sorted_face_index_ele.push_front(
23407 unsorted_face_index_ele[iproc][
e]);
23408 if (!treat_as_inverted[iproc][
e])
23411 is_inverted[tmp_ele_pt] =
true;
23416 is_inverted[tmp_ele_pt] =
false;
23419 new_element_added =
true;
23422 element_added_to_the_left =
true;
23425 else if (final_node_pt == first_node_pt
23426 && !connection_to_the_right)
23429 new_added_node_pt = final_node_pt = last_node_pt;
23431 tmp_sorted_nodes_pt.push_back(last_node_pt);
23434 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23436 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23439 tmp_sorted_face_index_ele.push_back(
23440 unsorted_face_index_ele[iproc][
e]);
23441 if (!treat_as_inverted[iproc][
e])
23444 is_inverted[tmp_ele_pt] =
false;
23449 is_inverted[tmp_ele_pt] =
true;
23452 new_element_added =
true;
23455 element_added_to_the_right =
true;
23458 else if (final_node_pt == last_node_pt &&
23459 !connection_to_the_right)
23462 new_added_node_pt = final_node_pt = first_node_pt;
23464 tmp_sorted_nodes_pt.push_back(first_node_pt);
23467 tmp_sorted_face_ele_pt.push_back(tmp_ele_pt);
23469 tmp_sorted_ele_pt.push_back(unsorted_ele_pt[iproc][
e]);
23472 tmp_sorted_face_index_ele.push_back(
23473 unsorted_face_index_ele[iproc][
e]);
23474 if (!treat_as_inverted[iproc][
e])
23477 is_inverted[tmp_ele_pt] =
true;
23482 is_inverted[tmp_ele_pt] =
false;
23485 new_element_added =
true;
23488 element_added_to_the_right =
true;
23492 if (new_element_added)
23495 done_ele[tmp_ele_pt] =
true;
23497 nsorted_face_ele++;
23501 const unsigned new_added_node_degree =
23502 global_node_degree[new_added_node_pt];
23511 if (element_added_to_the_left && !connection_to_the_left)
23514 bound_id_connection_to_the_left =
23515 this->check_connections_of_polyline_nodes(
23516 element_in_processor_pt,
23517 root_edge_bound_id,
23519 node_on_bnd_not_overlapped_by_shd_bnd,
23520 tmp_sorted_nodes_pt,
23521 local_shd_bnd_id_to_sorted_list_node_pt,
23522 new_added_node_degree,
23524 called_for_load_balance);
23528 if (bound_id_connection_to_the_left != -1)
23530 connection_to_the_left =
true;
23540 if (element_added_to_the_right && !connection_to_the_right)
23543 bound_id_connection_to_the_right =
23544 this->check_connections_of_polyline_nodes(
23545 element_in_processor_pt,
23546 root_edge_bound_id,
23548 node_on_bnd_not_overlapped_by_shd_bnd,
23549 tmp_sorted_nodes_pt,
23550 local_shd_bnd_id_to_sorted_list_node_pt,
23551 new_added_node_degree,
23553 called_for_load_balance);
23557 if (bound_id_connection_to_the_right != -1)
23559 connection_to_the_right =
true;
23568 if (connection_to_the_left && connection_to_the_right)
23569 {current_polyline_has_connections_at_both_ends =
true;}
23594 for (std::list<FiniteElement*>::iterator it =
23595 tmp_sorted_ele_pt.begin(); it != tmp_sorted_ele_pt.end(); it++)
23597 tmp_vector_sorted_ele_pt.push_back((*it));
23604 for (std::list<FiniteElement*>::iterator it =
23605 tmp_sorted_face_ele_pt.begin();
23606 it != tmp_sorted_face_ele_pt.end(); it++)
23608 tmp_vector_sorted_face_ele_pt.push_back((*it));
23614 for (std::list<int>::iterator it =
23615 tmp_sorted_face_index_ele.begin();
23616 it != tmp_sorted_face_index_ele.end(); it++)
23618 tmp_vector_sorted_face_index_ele.push_back((*it));
23633 Vector<int> final_bound_id_connection_to_the_left;
23636 Vector<int> final_bound_id_connection_to_the_right;
23639 this->break_loops_on_shared_polyline_load_balance_helper(
23641 tmp_sorted_nodes_pt,
23642 tmp_vector_sorted_ele_pt,
23643 tmp_vector_sorted_face_ele_pt, tmp_vector_sorted_face_index_ele,
23644 bound_id_connection_to_the_left, bound_id_connection_to_the_right,
23645 final_sorted_nodes_pt,
23646 final_boundary_element_pt,
23647 final_boundary_face_element_pt, final_face_index_element,
23648 final_bound_id_connection_to_the_left,
23649 final_bound_id_connection_to_the_right);
23652 const unsigned n_final_sorted_nodes = final_sorted_nodes_pt.size();
23655 for (
unsigned i = 0;
i < n_final_sorted_nodes;
i++)
23659 local_shd_bnd_id_to_sorted_list_node_pt[local_shd_bnd_id] =
23660 final_sorted_nodes_pt[
i];
23664 proc_local_shared_boundary_id[iproc].push_back(local_shd_bnd_id);
23669 local_shd_bnd_id++;
23672 sorted_ele_pt[iproc].push_back(final_boundary_element_pt[
i]);
23675 sorted_face_ele_pt[iproc].
23676 push_back(final_boundary_face_element_pt[
i]);
23679 sorted_face_index_ele[iproc].push_back(final_face_index_element[
i]);
23682 edge_boundary_id[iproc].push_back(root_edge_bound_id);
23689 bnd_connections_ids[0] = final_bound_id_connection_to_the_left[
i];
23690 bnd_connections_ids[1] = final_bound_id_connection_to_the_right[
i];
23691 sorted_connection_info[iproc].push_back(bnd_connections_ids);
23703 if (Print_timings_level_load_balance>2)
23705 oomph_info <<
"CPU for joining shared boundary face elements (load balance) [9.5]: "
23734 double tt_start_get_new_shared_boundaries_ids=0.0;
23735 if (Print_timings_level_load_balance>2)
23743 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23746 if (iproc != my_rank)
23750 nshared_boundaries_with_processor[iproc] =
23751 sorted_face_ele_pt[iproc].size();
23761 const unsigned root_processor = 0;
23772 MPI_Gather(&nshared_boundaries_with_processor[0],
23777 &flat_unsigned_root_received_data[0],
23785 comm_pt->mpi_comm());
23794 unsigned new_initial_shared_boundary_id = 0;
23795 unsigned new_final_shared_boundary_id = 0;
23798 if (my_rank == root_processor)
23805 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23808 root_nshared_bound_proc_with_proc[iproc].resize(nproc);
23811 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23813 root_nshared_bound_proc_with_proc[iproc][jproc] =
23814 flat_unsigned_root_received_data[(iproc * nproc) + jproc];
23823 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23825 for (
unsigned jproc = 0; jproc < iproc; jproc++)
23827 if (root_nshared_bound_proc_with_proc[iproc][jproc] !=
23828 root_nshared_bound_proc_with_proc[jproc][iproc])
23830 std::ostringstream error_stream;
23832 <<
"ROOT PROCESSOR ERROR\n\n"
23833 <<
"The number of shared boundaries between processor ("
23834 << iproc <<
") and (" << jproc <<
") is not the same:\n"
23835 <<
"Shared boundaries of processor (" << iproc
23836 <<
") with processor (" << jproc <<
"): ("
23837 << root_nshared_bound_proc_with_proc[iproc][jproc] <<
")\n"
23838 <<
"Shared boundaries of processor (" << jproc
23839 <<
") with processor (" << iproc <<
"): ("
23840 << root_nshared_bound_proc_with_proc[jproc][iproc] <<
")\n\n";
23842 OOMPH_CURRENT_FUNCTION,
23843 OOMPH_EXCEPTION_LOCATION);
23862 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23863 {start_shared_bound_id_proc_with_proc[iproc].resize(nproc);}
23867 unsigned shared_bound_id = this->nboundary();
23870 new_initial_shared_boundary_id = shared_bound_id;
23873 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23875 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
23878 if (root_nshared_bound_proc_with_proc[iproc][jproc] > 0)
23882 start_shared_bound_id_proc_with_proc[iproc][jproc] = shared_bound_id;
23883 start_shared_bound_id_proc_with_proc[jproc][iproc] = shared_bound_id;
23887 shared_bound_id+= root_nshared_bound_proc_with_proc[iproc][jproc];
23895 new_final_shared_boundary_id = shared_bound_id;
23902 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23904 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23908 const unsigned initial_shd_bnd_id =
23909 start_shared_bound_id_proc_with_proc[iproc][jproc];
23910 flat_unsigned_root_send_receive_data.push_back(initial_shd_bnd_id);
23914 const unsigned nshared_bnd_iproc_jproc =
23915 root_nshared_bound_proc_with_proc[iproc][jproc];
23916 flat_unsigned_root_send_receive_data.push_back(nshared_bnd_iproc_jproc);
23924 flat_unsigned_root_send_receive_data.
23925 push_back(new_initial_shared_boundary_id);
23928 flat_unsigned_root_send_receive_data.
23929 push_back(new_final_shared_boundary_id);
23940 unsigned root_ndata_sent_to_all_proc =
23941 flat_unsigned_root_send_receive_data.size();
23943 MPI_Bcast(&root_ndata_sent_to_all_proc,
23944 1, MPI_UNSIGNED, root_processor,
23945 comm_pt->mpi_comm());
23948 if (my_rank != root_processor)
23950 flat_unsigned_root_send_receive_data.resize(root_ndata_sent_to_all_proc);
23955 MPI_Bcast(&flat_unsigned_root_send_receive_data[0],
23958 root_ndata_sent_to_all_proc,
23962 comm_pt->mpi_comm());
23974 unsigned iflat_counter = 0;
23976 for (
unsigned iproc = 0; iproc < nproc; iproc++)
23979 initial_shared_bound_id_proc_with_proc[iproc].resize(nproc);
23980 nshared_bound_proc_with_proc[iproc].resize(nproc);
23983 for (
unsigned jproc = 0; jproc < nproc; jproc++)
23987 initial_shared_bound_id_proc_with_proc[iproc][jproc] =
23988 flat_unsigned_root_send_receive_data[iflat_counter++];
23992 nshared_bound_proc_with_proc[iproc][jproc] =
23993 flat_unsigned_root_send_receive_data[iflat_counter++];
24000 new_initial_shared_boundary_id =
24001 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-2];
24004 new_final_shared_boundary_id =
24005 flat_unsigned_root_send_receive_data[root_ndata_sent_to_all_proc-1];
24008 if (Print_timings_level_load_balance>2)
24010 oomph_info <<
"CPU for computing new shared boundaries ids (load balance) [9.6]: "
24032 double tt_start_create_new_shared_boundaries_polylines=0.0;
24033 if (Print_timings_level_load_balance>2)
24045 this->flush_shared_boundary_polyline_pt();
24046 this->Shared_boundary_polyline_pt.resize(nproc);
24049 this->Shared_boundaries_ids.clear();
24050 this->Shared_boundaries_ids.resize(nproc);
24051 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24053 this->Shared_boundaries_ids[iproc].clear();
24054 this->Shared_boundaries_ids[iproc].resize(nproc);
24058 this->Shared_boundary_from_processors.clear();
24059 this->Shared_boundary_overlaps_internal_boundary.clear();
24060 this->Boundary_was_splitted.clear();
24061 this->Boundary_subpolylines.clear();
24062 this->Boundary_marked_as_shared_boundary.clear();
24065 this->flush_shared_boundary_element();
24066 this->flush_face_index_at_shared_boundary();
24067 this->flush_shared_boundary_node();
24068 this->flush_sorted_shared_boundary_node();
24072 const unsigned old_local_shd_bnd_id = this->Initial_shared_boundary_id;
24075 this->Initial_shared_boundary_id = new_initial_shared_boundary_id;
24076 this->Final_shared_boundary_id = new_final_shared_boundary_id;
24086 std::map<unsigned, unsigned> local_to_global_shd_bnd_id;
24093 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24099 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24104 if (iproc == my_rank || jproc == my_rank)
24107 unsigned ref_proc = 0;
24108 if (iproc == my_rank)
24109 {ref_proc = jproc;}
24110 else if (jproc == my_rank)
24111 {ref_proc = iproc;}
24115 const unsigned nshared_bound_iproc_jproc =
24116 nshared_bound_proc_with_proc[iproc][jproc];
24119 for (
unsigned counter = 0;
24120 counter < nshared_bound_iproc_jproc;
24124 const unsigned shd_bnd_id =
24125 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24128 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24129 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24134 processors[0] = iproc;
24135 processors[1] = jproc;
24136 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24141 int root_edge_bound_id = edge_boundary_id[ref_proc][counter];
24144 if (root_edge_bound_id != -1)
24148 this->Shared_boundary_overlaps_internal_boundary[shd_bnd_id] =
24149 static_cast<unsigned>(root_edge_bound_id);
24162 sorted_face_ele_pt[ref_proc][counter][0];
24165 const unsigned first_face_ele_nnodes = first_face_ele_pt->
nnode();
24166 if (!is_inverted[first_face_ele_pt])
24169 Node* first_node_pt = first_face_ele_pt->node_pt(0);
24171 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24173 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24178 Node* first_node_pt =
24179 first_face_ele_pt->node_pt(first_face_ele_nnodes - 1);
24181 node_pt_to_create_shared_polyline.push_back(first_node_pt);
24183 this->add_shared_boundary_node(shd_bnd_id, first_node_pt);
24191 const unsigned nshared_boundary_elements =
24192 sorted_face_ele_pt[ref_proc][counter].size();
24196 for (
unsigned ie = 0 ; ie < nshared_boundary_elements; ie++)
24199 FiniteElement* bulk_ele_pt = sorted_ele_pt[ref_proc][counter][ie];
24203 this->add_shared_boundary_element(shd_bnd_id,
24208 const int face_index =
24209 sorted_face_index_ele[ref_proc][counter][ie];
24213 this->add_face_index_at_shared_boundary(shd_bnd_id,
24218 sorted_face_ele_pt[ref_proc][counter][ie];
24221 const unsigned nnodes = face_ele_pt->
nnode();
24222 if (!is_inverted[face_ele_pt])
24226 for (
unsigned n = 1;
n < nnodes;
n++)
24229 Node* node_pt = face_ele_pt->node_pt(
n);
24231 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24237 Node* last_node_pt = face_ele_pt->node_pt(nnodes - 1);
24238 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24244 for (
int n = nnodes-2;
n >= 0;
n--)
24247 Node* node_pt = face_ele_pt->node_pt(
n);
24249 this->add_shared_boundary_node(shd_bnd_id, node_pt);
24255 Node* last_node_pt = face_ele_pt->node_pt(0);
24256 node_pt_to_create_shared_polyline.push_back(last_node_pt);
24263 const unsigned nnodes_to_create_shared_boundary =
24264 node_pt_to_create_shared_polyline.size();
24268 for (
unsigned n = 0;
n < nnodes_to_create_shared_boundary;
n++)
24270 vertices[
n].resize(2);
24272 Node* tmp_node_pt = node_pt_to_create_shared_polyline[
n];
24274 vertices[
n][0] = tmp_node_pt->
x(0);
24275 vertices[
n][1] = tmp_node_pt->
x(1);
24283 this->Boundary_curve_section_pt[shd_bnd_id] = polyline_pt;
24287 unsorted_polylines_pt.push_back(polyline_pt);
24290 this->Free_curve_section_pt.insert(polyline_pt);
24296 const unsigned local_shd_bnd_id =
24297 proc_local_shared_boundary_id[ref_proc][counter];
24301 local_to_global_shd_bnd_id[local_shd_bnd_id] = shd_bnd_id;
24308 int tmp_bnd_id_connection_to_the_left =
24309 sorted_connection_info[ref_proc][counter][0];
24311 int tmp_bnd_id_connection_to_the_right =
24312 sorted_connection_info[ref_proc][counter][1];
24316 int bnd_id_connection_to_the_left = -1;
24317 int bnd_id_connection_to_the_right = -1;
24324 if (tmp_bnd_id_connection_to_the_left == -2)
24327 bnd_id_connection_to_the_left = shd_bnd_id;
24331 if (tmp_bnd_id_connection_to_the_left == -3)
24334 bnd_id_connection_to_the_left = -1;
24339 if (tmp_bnd_id_connection_to_the_left >=
24340 static_cast<int>(old_local_shd_bnd_id))
24345 std::map<unsigned, unsigned>::iterator it =
24346 local_to_global_shd_bnd_id.find(
24347 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left));
24350 if (it==local_to_global_shd_bnd_id.end())
24352 std::stringstream error_message;
24354 <<
"The global shared boundary id was not found for\n"
24355 <<
"the local shared boundary shared with processor ("
24356 << ref_proc <<
").\n"
24357 <<
"This processor: (" << my_rank <<
")\n"
24358 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24359 <<
"Local shared boundary: ("
24360 << tmp_bnd_id_connection_to_the_left <<
")\n";
24362 OOMPH_CURRENT_FUNCTION,
24363 OOMPH_EXCEPTION_LOCATION);
24368 bnd_id_connection_to_the_left =
24369 local_to_global_shd_bnd_id[
24370 static_cast<unsigned>(tmp_bnd_id_connection_to_the_left)];
24377 bnd_id_connection_to_the_left =
24378 tmp_bnd_id_connection_to_the_left;
24387 if (tmp_bnd_id_connection_to_the_right == -2)
24390 bnd_id_connection_to_the_right = shd_bnd_id;
24394 if (tmp_bnd_id_connection_to_the_right == -3)
24397 bnd_id_connection_to_the_right = -1;
24402 if (tmp_bnd_id_connection_to_the_right >=
24403 static_cast<int>(old_local_shd_bnd_id))
24408 std::map<unsigned, unsigned>::iterator it =
24409 local_to_global_shd_bnd_id.find(
24410 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right));
24413 if (it==local_to_global_shd_bnd_id.end())
24415 std::stringstream error_message;
24417 <<
"The global shared boundary id was not found for\n"
24418 <<
"the local shared boundary shared with processor ("
24419 << ref_proc <<
").\n"
24420 <<
"This processor: (" << my_rank <<
")\n"
24421 <<
"Boundary shared with processor: (" << ref_proc <<
")\n"
24422 <<
"Local shared boundary: ("
24423 << tmp_bnd_id_connection_to_the_right <<
")\n";
24425 OOMPH_CURRENT_FUNCTION,
24426 OOMPH_EXCEPTION_LOCATION);
24430 bnd_id_connection_to_the_right =
24431 local_to_global_shd_bnd_id[
24432 static_cast<unsigned>(tmp_bnd_id_connection_to_the_right)];
24439 bnd_id_connection_to_the_right =
24440 tmp_bnd_id_connection_to_the_right;
24446 if (bnd_id_connection_to_the_left != -1)
24449 const unsigned ubnd_id_connection_to_the_left =
24450 static_cast<unsigned>(bnd_id_connection_to_the_left);
24455 ubnd_id_connection_to_the_left;
24463 if (bnd_id_connection_to_the_right != -1)
24467 const unsigned ubnd_id_connection_to_the_right =
24468 static_cast<unsigned>(bnd_id_connection_to_the_right);
24473 ubnd_id_connection_to_the_right;
24489 const unsigned nshared_bound_iproc_jproc =
24490 nshared_bound_proc_with_proc[iproc][jproc];
24492 for (
unsigned counter = 0;
24493 counter < nshared_bound_iproc_jproc;
24497 const unsigned shd_bnd_id =
24498 initial_shared_bound_id_proc_with_proc[iproc][jproc] + counter;
24501 this->Shared_boundaries_ids[iproc][jproc].push_back(shd_bnd_id);
24502 this->Shared_boundaries_ids[jproc][iproc].push_back(shd_bnd_id);
24507 processors[0] = iproc;
24508 processors[1] = jproc;
24509 this->Shared_boundary_from_processors[shd_bnd_id] = processors;
24520 if (Print_timings_level_load_balance>2)
24522 oomph_info <<
"CPU for creating new shared boundaries representations (load balance) [9.7]: "
24541 double tt_start_create_new_shared_curves=0.0;
24542 if (Print_timings_level_load_balance>2)
24549 if (unsorted_polylines_pt.size() > 0)
24553 this->sort_polylines_helper(unsorted_polylines_pt,
24554 this->Shared_boundary_polyline_pt[my_rank]);
24558 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24560 const unsigned nface_ele = unsorted_face_ele_pt[iproc].size();
24561 for (
unsigned e = 0;
e < nface_ele;
e++)
24563 delete unsorted_face_ele_pt[iproc][
e];
24564 unsorted_face_ele_pt[iproc][
e] = 0;
24570 if (Print_timings_level_load_balance>2)
24572 oomph_info <<
"CPU for creating the new shared curves (load balance) [9.8]: "
24591 template <
class ELEMENT>
24594 &unsorted_face_ele_pt,
24595 std::map<Node*, unsigned>
24596 &global_node_degree)
24599 const unsigned nproc = this->communicator_pt()->nproc();
24600 const unsigned my_rank = this->communicator_pt()->my_rank();
24611 std::map<Node*, Vector<Vector<unsigned> > > node_alias;
24619 create_adjacency_matrix_new_shared_edges_helper(unsorted_face_ele_pt,
24620 tmp_sorted_shared_node_pt,
24622 local_adjacency_matrix);
24635 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24638 package_unsigned_send_data_to_root.push_back(iproc);
24641 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
24644 package_unsigned_send_data_to_root.push_back(n_nodes);
24647 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
24650 Node* shd_node_pt = tmp_sorted_shared_node_pt[iproc][ishd];
24656 const unsigned n_alias = alias_node_info.size();
24659 package_unsigned_send_data_to_root.push_back(n_alias);
24662 for (
unsigned i = 0;
i < n_alias;
i++)
24666 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][0]);
24668 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][1]);
24670 package_unsigned_send_data_to_root.push_back(alias_node_info[
i][2]);
24676 for (
unsigned i = 0;
i < n_nodes;
i++)
24678 for (
unsigned j = 0; j < n_nodes; j++)
24681 package_unsigned_send_data_to_root.
24682 push_back(local_adjacency_matrix[iproc][
i][j]);
24691 const unsigned root_processor = 0;
24697 unsigned n_unsigned_data_send_to_root =
24698 package_unsigned_send_data_to_root.size();
24701 Vector<int> n_unsigned_data_received_in_root(nproc, 0);
24705 MPI_Gather(&n_unsigned_data_send_to_root,
24709 &n_unsigned_data_received_in_root[0],
24717 comm_pt->mpi_comm());
24720 unsigned n_unsigned_total_data_receive_in_root = 0;
24721 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24724 n_unsigned_total_data_receive_in_root+=
24725 n_unsigned_data_received_in_root[iproc];
24729 Vector<int> root_unsigned_offsets_receive(nproc,0);
24730 root_unsigned_offsets_receive[0] = 0;
24731 for (
unsigned iproc = 1; iproc < nproc; iproc++)
24735 root_unsigned_offsets_receive[iproc] =
24736 root_unsigned_offsets_receive[iproc-1] +
24737 n_unsigned_data_received_in_root[iproc-1];
24741 if (package_unsigned_send_data_to_root.size()==0)
24743 package_unsigned_send_data_to_root.resize(1);
24748 package_unsigned_data_received_root(n_unsigned_total_data_receive_in_root);
24749 if (my_rank!=root_processor)
24752 if (package_unsigned_data_received_root.size()==0)
24754 package_unsigned_data_received_root.resize(1);
24759 MPI_Gatherv(&package_unsigned_send_data_to_root[0],
24764 n_unsigned_data_send_to_root,
24768 &package_unsigned_data_received_root[0],
24774 &n_unsigned_data_received_in_root[0],
24777 &root_unsigned_offsets_receive[0],
24784 comm_pt->mpi_comm());
24789 Vector<int> n_unsigned_data_sent_from_root(nproc, 0);
24793 if (my_rank == root_processor)
24797 unsigned decode_counter = 0;
24806 local_node_alias(nproc);
24811 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24813 local_node_alias[iproc].resize(nproc);
24817 local_adjacency_matrix[iproc].resize(nproc);
24819 if (n_unsigned_data_received_in_root[iproc] > 0)
24823 for (
unsigned jproc = 0; jproc < nproc; jproc++)
24826 const unsigned read_jproc =
24827 package_unsigned_data_received_root[decode_counter++];
24831 if (read_jproc != jproc)
24833 std::ostringstream error_stream;
24835 <<
"The read processor is different from the jproc, this is\n"
24836 <<
"a synchronisation issue. The data are not read in the\n"
24837 <<
"sameorder as the were packaged\n"
24838 <<
"Read processor: (" << read_jproc <<
")\n"
24839 <<
"Current jproc: (" << jproc <<
")\n\n";
24841 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24842 OOMPH_EXCEPTION_LOCATION);
24847 const unsigned read_n_shd_nodes_iproc_jproc =
24848 package_unsigned_data_received_root[decode_counter++];
24851 local_node_alias[iproc][jproc].resize(read_n_shd_nodes_iproc_jproc);
24855 for (
unsigned ishd = 0; ishd < read_n_shd_nodes_iproc_jproc; ishd++)
24858 const unsigned read_n_alias_node_iproc_jproc =
24859 package_unsigned_data_received_root[decode_counter++];
24862 local_node_alias[iproc][jproc][ishd].
24863 resize(read_n_alias_node_iproc_jproc);
24865 for (
unsigned ialias = 0;
24866 ialias < read_n_alias_node_iproc_jproc; ialias++)
24870 local_node_alias[iproc][jproc][ishd][ialias].resize(3);
24873 local_node_alias[iproc][jproc][ishd][ialias][0] =
24874 package_unsigned_data_received_root[decode_counter++];
24877 local_node_alias[iproc][jproc][ishd][ialias][1] =
24878 package_unsigned_data_received_root[decode_counter++];
24881 local_node_alias[iproc][jproc][ishd][ialias][2] =
24882 package_unsigned_data_received_root[decode_counter++];
24889 local_adjacency_matrix[iproc][jproc].
24890 resize(read_n_shd_nodes_iproc_jproc);
24892 for (
unsigned i = 0;
i < read_n_shd_nodes_iproc_jproc;
i++)
24895 local_adjacency_matrix[iproc][jproc][
i].
24896 resize(read_n_shd_nodes_iproc_jproc);
24897 for (
unsigned j = 0; j < read_n_shd_nodes_iproc_jproc; j++)
24900 local_adjacency_matrix[iproc][jproc][
i][j] =
24901 package_unsigned_data_received_root[decode_counter++];
24913 if (decode_counter != n_unsigned_total_data_receive_in_root)
24915 std::ostringstream error_stream;
24917 <<
"The number of data decoded in root received from others\n"
24918 <<
"processors is different from the total number of data received\n"
24919 <<
"Data decoded: (" << decode_counter <<
")\n"
24920 <<
"Data received: ("<<n_unsigned_total_data_receive_in_root<<
")\n\n"
24921 <<
"This is a synchronisation issue so you are probably sending\n"
24922 <<
"more or less info. than the one that is being decoded\n\n";
24924 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24925 OOMPH_EXCEPTION_LOCATION);
24935 std::map<Vector<unsigned>,
bool> alias_done;
24941 for (
unsigned iproc = 0; iproc < nproc; iproc++)
24943 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
24946 const unsigned n_shd_nodes_iproc_jproc =
24947 local_node_alias[iproc][jproc].size();
24950 const unsigned n_shd_nodes_jproc_iproc =
24951 local_node_alias[jproc][iproc].size();
24953 if (n_shd_nodes_iproc_jproc != n_shd_nodes_jproc_iproc)
24955 std::ostringstream error_stream;
24957 <<
"The number of nodes shared between iproc and jproc is\n"
24958 <<
"different from the number of nodes shared between jproc\n"
24960 <<
"Nodes shared between processor (" << iproc <<
") and "
24961 <<
"processor ("<<jproc<<
"): ("<<n_shd_nodes_iproc_jproc<<
")\n"
24962 <<
"Nodes shared between processor (" << jproc <<
") and "
24963 <<
"processor ("<<iproc<<
"): ("<<n_shd_nodes_jproc_iproc<<
")\n\n";
24965 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
24966 OOMPH_EXCEPTION_LOCATION);
24971 for (
unsigned ishd = 0; ishd < n_shd_nodes_iproc_jproc; ishd++)
24975 const unsigned n_alias_iproc_jproc =
24976 local_node_alias[iproc][jproc][ishd].size();
24977 const unsigned n_alias_jproc_iproc =
24978 local_node_alias[jproc][iproc][ishd].size();
24984 bool new_alias_added =
false;
24987 for (
unsigned ialias = 0; ialias < n_alias_iproc_jproc; ialias++)
24991 local_node_alias[iproc][jproc][ishd][ialias];
24993 if (!alias_done[current_alias])
24996 node_alias.push_back(current_alias);
24998 new_alias_added =
true;
25000 alias_done[current_alias] =
true;
25006 for (
unsigned ialias = 0; ialias < n_alias_jproc_iproc; ialias++)
25010 local_node_alias[jproc][iproc][ishd][ialias];
25013 if (!alias_done[current_alias])
25016 node_alias.push_back(current_alias);
25018 new_alias_added =
true;
25020 alias_done[current_alias] =
true;
25025 unsigned counter_alias = 0;
25029 unsigned n_current_alias = node_alias.size();
25030 while(new_alias_added || counter_alias < n_current_alias)
25033 new_alias_added =
false;
25039 local_node_alias[current_alias[0]]
25041 [current_alias[2]];
25045 const unsigned n_alias = alias_of_current_alias.size();
25049 for (
unsigned k = 0; k < n_alias; k++)
25053 alias_of_current_alias[k];
25056 if (!alias_done[add_alias])
25059 node_alias.push_back(add_alias);
25062 new_alias_added =
true;
25064 alias_done[add_alias] =
true;
25072 local_node_alias[current_alias[1]]
25074 [current_alias[2]];
25078 const unsigned n_alias2 = alias_of_current_alias2.size();
25082 for (
unsigned k = 0; k < n_alias2; k++)
25086 alias_of_current_alias2[k];
25089 if (!alias_done[add_alias])
25092 node_alias.push_back(add_alias);
25095 new_alias_added =
true;
25097 alias_done[add_alias] =
true;
25108 n_current_alias = node_alias.size();
25114 if (node_alias.size() > 0)
25118 global_node_alias.push_back(node_alias);
25131 const unsigned n_global_shared_nodes = global_node_alias.size();
25137 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25140 local_to_global_shared_node[iproc].resize(nproc);
25145 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25148 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25151 const unsigned n_shd_nodes =
25152 local_node_alias[iproc][jproc].size();
25155 local_to_global_shared_node[iproc][jproc].resize(n_shd_nodes,-1);
25158 local_to_global_shared_node[jproc][iproc].resize(n_shd_nodes,-1);
25168 for (
unsigned k = 0 ; k < n_global_shared_nodes; k++)
25171 const unsigned n_alias_global_node = global_node_alias[k].size();
25173 for (
unsigned l = 0; l < n_alias_global_node; l++)
25176 const unsigned iproc = global_node_alias[k][l][0];
25178 const unsigned jproc = global_node_alias[k][l][1];
25180 const unsigned ishd = global_node_alias[k][l][2];
25182 local_to_global_shared_node[iproc][jproc][ishd] = k;
25191 for (
unsigned k = 0; k < n_global_shared_nodes; k++)
25194 global_adjacency_matrix[k].resize(n_global_shared_nodes,0);
25204 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25207 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25210 const unsigned n_shd_nodes =
25211 local_node_alias[iproc][jproc].size();
25218 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25220 for (
unsigned jshd = ishd + 1; jshd < n_shd_nodes; jshd++)
25223 if (local_adjacency_matrix[iproc][jproc][ishd][jshd] > 0)
25228 const int global_shd_node_left =
25229 local_to_global_shared_node[iproc][jproc][ishd];
25232 const int global_shd_node_right =
25233 local_to_global_shared_node[iproc][jproc][jshd];
25238 if (global_shd_node_left == -1)
25240 std::ostringstream error_stream;
25242 <<
"The local node in processors iproc and jproc has no\n"
25243 <<
"global node assigned\n"
25244 <<
"iproc processor: (" << iproc <<
")\n"
25245 <<
"jproc processor: ("<<jproc<<
")\n"
25246 <<
"Local node: (" << ishd <<
")\n\n";
25248 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25249 OOMPH_EXCEPTION_LOCATION);
25254 if (global_shd_node_right == -1)
25256 std::ostringstream error_stream;
25258 <<
"The local node in processors iproc and jproc has no\n"
25259 <<
"global node assigned\n"
25260 <<
"iproc processor: (" << iproc <<
")\n"
25261 <<
"jproc processor: ("<<jproc<<
")\n"
25262 <<
"Local node: (" << jshd <<
")\n\n";
25264 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25265 OOMPH_EXCEPTION_LOCATION);
25269 const unsigned uleft =
25270 static_cast<unsigned>(global_shd_node_left);
25271 const unsigned uright =
25272 static_cast<unsigned>(global_shd_node_right);
25275 global_adjacency_matrix[uleft][uright]++;
25278 global_adjacency_matrix[uright][uleft]++;
25281 global_node_degree[uleft]++;
25284 global_node_degree[uright]++;
25300 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25302 root_local_node_degree[iproc].resize(nproc);
25306 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25309 for (
unsigned jproc = iproc + 1; jproc < nproc; jproc++)
25313 const unsigned n_shd_nodes = local_node_alias[iproc][jproc].size();
25316 root_local_node_degree[iproc][jproc].resize(n_shd_nodes);
25318 root_local_node_degree[jproc][iproc].resize(n_shd_nodes);
25322 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25325 const int global_shd_node_id =
25326 local_to_global_shared_node[iproc][jproc][ishd];
25330 if (global_shd_node_id == -1)
25332 std::ostringstream error_stream;
25334 <<
"The local node in processors iproc and jproc has no\n"
25335 <<
"global node assigned\n"
25336 <<
"iproc processor: (" << iproc <<
")\n"
25337 <<
"jproc processor: ("<<jproc<<
")\n"
25338 <<
"Local node: (" << ishd <<
")\n\n";
25340 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25341 OOMPH_EXCEPTION_LOCATION);
25346 const unsigned uglobal_shd_node_id =
25347 static_cast<unsigned>(global_shd_node_id);
25350 const unsigned node_degree =
25351 global_node_degree[uglobal_shd_node_id];
25355 root_local_node_degree[iproc][jproc][ishd] = node_degree;
25357 root_local_node_degree[jproc][iproc][ishd] = node_degree;
25367 package_unsigned_data_sent_from_root.clear();
25371 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25374 unsigned count_n_data_sent_to_iproc = 0;
25375 for (
unsigned jproc = 0; jproc < nproc; jproc++)
25378 if (iproc != jproc)
25381 const unsigned n_shd_nodes =
25382 root_local_node_degree[iproc][jproc].size();
25385 count_n_data_sent_to_iproc+=n_shd_nodes;
25388 for (
unsigned ishd = 0; ishd < n_shd_nodes; ishd++)
25390 package_unsigned_data_sent_from_root.
25391 push_back(root_local_node_degree[iproc][jproc][ishd]);
25399 n_unsigned_data_sent_from_root[iproc] = count_n_data_sent_to_iproc;
25406 int n_unsigned_data_received_from_root = 0;
25409 MPI_Scatter(&n_unsigned_data_sent_from_root[0],
25415 &n_unsigned_data_received_from_root,
25422 comm_pt->mpi_comm());
25426 package_unsigned_data_received_from_root(n_unsigned_data_received_from_root);
25430 root_unsigned_offsets_sent[0] = 0;
25431 for (
unsigned iproc = 1; iproc < nproc; iproc++)
25434 root_unsigned_offsets_sent[iproc] =
25435 root_unsigned_offsets_sent[iproc-1] +
25436 n_unsigned_data_sent_from_root[iproc-1];
25439 if (my_rank!=root_processor)
25442 if (package_unsigned_data_sent_from_root.size()==0)
25444 package_unsigned_data_sent_from_root.resize(1);
25449 if (package_unsigned_data_received_from_root.size()==0)
25451 package_unsigned_data_received_from_root.resize(1);
25455 MPI_Scatterv(&package_unsigned_data_sent_from_root[0],
25460 &n_unsigned_data_sent_from_root[0],
25464 &root_unsigned_offsets_sent[0],
25467 &package_unsigned_data_received_from_root[0],
25475 n_unsigned_data_received_from_root,
25483 comm_pt->mpi_comm());
25488 std::map<Node*, bool> node_done;
25492 int decode_counter = 0;
25496 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25499 if (iproc != my_rank)
25502 const unsigned n_nodes = tmp_sorted_shared_node_pt[iproc].size();
25505 package_unsigned_send_data_to_root.push_back(n_nodes);
25508 for (
unsigned ishd = 0; ishd < n_nodes; ishd++)
25512 const unsigned node_degree =
25513 package_unsigned_data_received_from_root[decode_counter++];
25516 Node* shd_node_pt =
25517 tmp_sorted_shared_node_pt[iproc][ishd];
25520 if (!node_done[shd_node_pt])
25523 global_node_degree[shd_node_pt] = node_degree;
25525 node_done[shd_node_pt] =
true;
25532 if (global_node_degree[shd_node_pt] != node_degree)
25534 std::ostringstream error_stream;
25536 <<
"The local node has already assigned a global degree,\n"
25537 <<
"however, a different degree for the same node has been\n"
25538 <<
"read from the data sent from root processor\n"
25539 <<
"iproc processor: (" << iproc <<
")\n"
25540 <<
"Local node: (" << ishd <<
")\n"
25541 <<
"---------------------------------------------------------\n"
25542 <<
"Already assigned degree: ("
25543 << global_node_degree[shd_node_pt] <<
")\n"
25544 <<
"New found degree: (" << node_degree <<
")\n"
25545 <<
"---------------------------------------------------------\n"
25546 <<
"Node coordinates: (" << shd_node_pt->x(0) <<
", "
25547 << shd_node_pt->x(1) <<
")\n\n";
25549 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25550 OOMPH_EXCEPTION_LOCATION);
25554 #endif // #ifdef PARANOID
25564 if (decode_counter != n_unsigned_data_received_from_root)
25566 std::ostringstream error_stream;
25568 <<
"The number of data decoded received from root processor is\n"
25569 <<
"different from the total number of data received from the root\n"
25571 <<
"Data decoded: (" << decode_counter <<
")\n"
25572 <<
"Data received: ("<<n_unsigned_data_received_from_root<<
")\n\n"
25573 <<
"This is a synchronisation issue so you are probably sending\n"
25574 <<
"more or less info. than the one that is being decoded\n\n";
25576 "RefineableTriangleMesh::compute_shared_node_degree_helper()",
25577 OOMPH_EXCEPTION_LOCATION);
25589 template <
class ELEMENT>
25598 const unsigned nproc = this->communicator_pt()->nproc();
25599 const unsigned my_rank = this->communicator_pt()->my_rank();
25608 node_alias.clear();
25614 for (
unsigned iproc = 0; iproc < nproc; iproc++)
25617 if (iproc != my_rank)
25620 std::map<Node*, bool> done_node;
25625 std::map<std::pair<double, double>,
Node*,
classcomp> sorted_nodes_pt;
25628 const unsigned n_unsorted_face_ele =
25629 unsorted_face_ele_pt[iproc].size();
25632 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25642 if (!done_node[left_node_pt])
25644 std::pair<double, double> vertex =
25645 std::make_pair(left_node_pt->x(0), left_node_pt->x(1));
25646 sorted_nodes_pt[vertex] = left_node_pt;
25648 done_node[left_node_pt] =
true;
25652 const unsigned n_nodes = face_ele_pt->
nnode();
25654 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes-1);
25659 if (!done_node[right_node_pt])
25661 std::pair<double, double> vertex =
25662 std::make_pair(right_node_pt->x(0), right_node_pt->x(1));
25663 sorted_nodes_pt[vertex] = right_node_pt;
25665 done_node[right_node_pt] =
true;
25674 unsigned counter = 0;
25678 for (std::map<std::pair<double, double>,
Node*>::iterator it
25679 = sorted_nodes_pt.begin(); it != sorted_nodes_pt.end(); it++)
25682 Node* node_pt = (*it).second;
25684 tmp_sorted_shared_node_pt[iproc].push_back(node_pt);
25687 tmp_node_index[iproc][node_pt] = counter;
25692 alias[0] = my_rank;
25696 alias[2] = counter++;
25699 node_alias[node_pt].push_back(alias);
25709 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25712 const unsigned n_shd_nodes = tmp_sorted_shared_node_pt[iproc].size();
25714 adjacency_matrix[iproc].resize(n_shd_nodes);
25715 for (
unsigned i = 0;
i < n_shd_nodes;
i++)
25718 adjacency_matrix[iproc][
i].resize(n_shd_nodes);
25721 for (
unsigned j = 0; j < n_shd_nodes; j++)
25723 adjacency_matrix[iproc][
i][j] = 0;
25731 for (
unsigned iproc = 0 ; iproc < nproc; iproc++)
25734 if (iproc != my_rank)
25737 const unsigned n_unsorted_face_ele =
25738 unsorted_face_ele_pt[iproc].size();
25741 for (
unsigned e = 0;
e < n_unsorted_face_ele;
e++)
25749 const unsigned n_nodes = face_ele_pt->
nnode();
25751 Node* right_node_pt = face_ele_pt->
node_pt(n_nodes-1);
25754 const unsigned left_node_index = tmp_node_index[iproc][left_node_pt];
25755 const unsigned right_node_index = tmp_node_index[iproc][right_node_pt];
25759 adjacency_matrix[iproc][left_node_index][right_node_index]++;
25761 adjacency_matrix[iproc][right_node_index][left_node_index]++;
25775 template <
class ELEMENT>
25781 tmp_segment_nodes.clear();
25795 const unsigned nshared_bound_ele =
25796 this->nshared_boundary_element(shd_bnd_id);
25800 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
25804 this->shared_boundary_element_pt(shd_bnd_id,
e);
25807 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
25818 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
25824 halo_shared_face_ele_pt.push_back(face_ele_pt);
25831 std::map<FiniteElement*, bool> shared_face_done;
25834 const unsigned nnonhalo_face_shared_ele =
25835 nonhalo_shared_face_ele_pt.size();
25841 const unsigned nhalo_face_shared_ele =
25842 halo_shared_face_ele_pt.size();
25846 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
25848 std::ostringstream error_message;
25850 <<
"The number of shared boundary elements (" << nshared_bound_ele
25851 <<
") is not the double\nof the number of unsorted nonhalo shared "
25852 <<
"face boundary elements (" << nnonhalo_face_shared_ele
25853 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25855 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25856 OOMPH_EXCEPTION_LOCATION);
25861 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
25863 std::ostringstream error_message;
25865 <<
"The number of shared boundary elements (" << nshared_bound_ele
25866 <<
") is not the double\nof the number of unsorted halo shared "
25867 <<
"face boundary elements (" << nhalo_face_shared_ele
25868 <<
")\n for the current boundary ("<< shd_bnd_id <<
")\n\n";
25870 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25871 OOMPH_EXCEPTION_LOCATION);
25877 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
25880 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
25883 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
25885 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
25886 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh-1);
25890 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
25893 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
25896 if (!shared_face_done[halo_face_ele_pt])
25899 const unsigned nnodes_h = halo_face_ele_pt->nnode();
25901 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
25902 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
25906 if (nh_first_node_pt == h_first_node_pt &&
25907 nh_last_node_pt == h_last_node_pt)
25910 shared_face_done[nonhalo_face_ele_pt] =
true;
25911 shared_face_done[halo_face_ele_pt] =
true;
25917 else if (nh_first_node_pt == h_last_node_pt &&
25918 nh_last_node_pt == h_first_node_pt)
25921 shared_face_done[nonhalo_face_ele_pt] =
true;
25922 shared_face_done[halo_face_ele_pt] =
true;
25937 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
25938 shared_face_done.size())
25940 std::ostringstream error_message;
25942 <<
"The number of DONE shared boundary face elements ("
25943 << shared_face_done.size() <<
") is not the same\n as the sum of"
25944 <<
"the nonhalo face shared boundary elements ("
25945 << nnonhalo_face_shared_ele <<
")\nand the halo face shared "
25946 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/"
25947 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
25949 "RefineableTriangleMesh::get_shared_boundary_segment_nodes_helper()",
25950 OOMPH_EXCEPTION_LOCATION);
25952 #endif // #ifdef PARANOID
25962 shared_face_done.clear();
25964 unsigned nsorted_face_ele = 0;
25967 std::list<Node*> sorted_nodes;
25970 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
25971 nsorted_face_ele++;
25974 shared_face_done[root_face_ele_pt] =
true;
25977 const unsigned nnodes_root = root_face_ele_pt->
nnode();
25978 Node *first_node_pt = root_face_ele_pt->
node_pt(0);
25979 Node *last_node_pt = root_face_ele_pt->
node_pt(nnodes_root-1);
25982 sorted_nodes.push_back(first_node_pt);
25983 sorted_nodes.push_back(last_node_pt);
25986 while (nsorted_face_ele < nnonhalo_face_shared_ele)
25989 bool node_added =
false;
25993 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
25996 nonhalo_shared_face_ele_pt[iface];
25999 if (!shared_face_done[tmp_shared_face_ele_pt])
26002 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
26005 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
26006 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
26008 if (left_node_pt == first_node_pt)
26011 sorted_nodes.push_front(right_node_pt);
26012 first_node_pt = right_node_pt;
26015 else if (left_node_pt == last_node_pt)
26018 sorted_nodes.push_back(right_node_pt);
26019 last_node_pt = right_node_pt;
26022 else if (right_node_pt == first_node_pt)
26025 sorted_nodes.push_front(left_node_pt);
26026 first_node_pt = left_node_pt;
26029 else if (right_node_pt == last_node_pt)
26032 sorted_nodes.push_back(left_node_pt);
26033 last_node_pt = left_node_pt;
26041 shared_face_done[tmp_shared_face_ele_pt] =
true;
26042 nsorted_face_ele++;
26058 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
26060 delete nonhalo_shared_face_ele_pt[inh];
26061 nonhalo_shared_face_ele_pt[inh] = 0;
26066 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
26068 delete halo_shared_face_ele_pt[ih];
26069 halo_shared_face_ele_pt[ih] = 0;
26077 const unsigned n_nodes = sorted_nodes.size();
26080 tmp_segment_nodes.resize(1);
26081 tmp_segment_nodes[0].resize(n_nodes);
26084 unsigned counter = 0;
26087 for (std::list<Node*>::iterator it = sorted_nodes.begin();
26088 it != sorted_nodes.end(); it++)
26090 tmp_segment_nodes[0][counter] = (*it);
26102 template<
class ELEMENT>
26110 const unsigned nbound = this->initial_shared_boundary_id();
26113 const unsigned nproc = this->communicator_pt()->nproc();
26121 unsigned counter_face_indexes = 0;
26123 for (
unsigned b = 0; b < nbound; b++)
26126 const unsigned nboundary_ele = nboundary_element(b);
26127 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26129 if (ele_pt == this->boundary_element_pt(b,
e))
26132 associated_boundaries.push_back(b);
26134 face_index_on_boundary.push_back(face_index_at_boundary(b,
e));
26135 counter_face_indexes++;
26137 if (counter_face_indexes > 2)
26139 std::stringstream error_message;
26141 <<
"A triangular element can not have more than two of its faces "
26142 <<
"on a boundary!!!\n\n";
26144 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26145 OOMPH_EXCEPTION_LOCATION);
26149 if (counter_face_indexes==2) {
break;}
26150 #endif // #ifdef PARANOID
26160 const unsigned nassociated_boundaries = associated_boundaries.size();
26161 if (nassociated_boundaries > 0)
26164 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26168 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26169 std::stringstream junk;
26170 junk <<
"The elements is associated to " << nassociated_boundaries <<
" boundaries";
26178 for (
unsigned i = 0;
i < nassociated_boundaries;
i++)
26180 unsigned b = associated_boundaries[
i];
26182 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26183 std::stringstream junk;
26184 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries <<
" total associated boundaries";
26187 unsigned f = face_index_on_boundary[
i];
26189 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26190 std::stringstream junk2;
26191 junk2 <<
"Face index " << f <<
" for associated boundary " << b;
26206 const unsigned n_regions = this->nregion();
26211 unsigned counter_face_indexes_in_regions = 0;
26213 for (
unsigned b = 0; b < nbound; b++)
26216 for (
unsigned i_reg = 0 ; i_reg < n_regions; i_reg++)
26219 const unsigned region_id =
26220 static_cast<unsigned>(this->Region_attribute[i_reg]);
26225 const unsigned nele_in_region =
26226 this->nboundary_element_in_region(b, region_id);
26227 for (
unsigned ee = 0; ee < nele_in_region; ee++)
26232 this->boundary_element_in_region_pt(b, region_id, ee))
26239 bound_and_region[0] = b;
26241 bound_and_region[1] = region_id;
26244 associated_boundaries_and_regions.push_back(bound_and_region);
26246 face_index_on_boundary_and_region.push_back(
26247 this->face_index_at_boundary_in_region(b,region_id,ee));
26251 counter_face_indexes_in_regions++;
26254 if (counter_face_indexes_in_regions > 2)
26256 std::stringstream error_message;
26258 <<
"A triangular element can not have more than two of its\n"
26259 <<
"faces on a boundary!!!\n\n";
26261 "RefineableTriangleMesh::get_required_elemental_information_helper()",
26262 OOMPH_EXCEPTION_LOCATION);
26277 const unsigned nassociated_boundaries_and_regions =
26278 associated_boundaries_and_regions.size();
26279 if (nassociated_boundaries_and_regions > 0)
26282 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26287 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26288 std::stringstream junk;
26289 junk <<
"The element is associated to " << nassociated_boundaries_and_regions <<
" boundaries-regions";
26297 for (
unsigned i = 0;
i < nassociated_boundaries_and_regions;
i++)
26299 const unsigned b = associated_boundaries_and_regions[
i][0];
26301 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26302 std::stringstream junk;
26303 junk <<
"Element associated to boundary " << b <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26307 const unsigned r = associated_boundaries_and_regions[
i][1];
26309 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26310 std::stringstream junk2;
26311 junk2 <<
"Element associated to region " << r <<
" of " << nassociated_boundaries_and_regions <<
" total associated boundaries-regions";
26315 const unsigned f = face_index_on_boundary_and_region[
i];
26317 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26318 std::stringstream junk3;
26319 junk3 <<
"Face index " << f <<
" for associated boundary-region (" << b <<
"-" << r <<
")";
26327 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26336 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26351 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
26354 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
26356 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
26359 const unsigned sb = my_rank_shared_boundaries_ids[
i];
26362 const unsigned nboundary_ele = this->nshared_boundary_element(sb);
26363 for (
unsigned e = 0;
e < nboundary_ele;
e++)
26365 if (ele_pt == this->shared_boundary_element_pt(sb,
e))
26368 associated_shared_boundaries.push_back(sb);
26370 face_index_on_shared_boundary.push_back(
26371 this->face_index_at_shared_boundary(sb,
e));
26378 const unsigned nassociated_shared_boundaries =
26379 associated_shared_boundaries.size();
26380 if (nassociated_shared_boundaries > 0)
26383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26387 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26388 std::stringstream junk;
26389 junk <<
"The elements is associated to " << nassociated_shared_boundaries <<
"shared boundaries";
26394 for (
unsigned i = 0;
i < nassociated_shared_boundaries;
i++)
26396 const unsigned b = associated_shared_boundaries[
i];
26398 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26399 std::stringstream junk;
26400 junk <<
"Element associated to shared boundary " << b <<
" of " << nassociated_shared_boundaries <<
" total associated boundaries";
26404 const unsigned f = face_index_on_shared_boundary[
i];
26406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26407 std::stringstream junk2;
26408 junk2 <<
"Face index " << f <<
" for associated shared boundary " << b;
26416 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26427 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26430 const unsigned n_haloed_jproc = f_haloed_ele_pt[jproc].size();
26432 for (
unsigned ihd =0; ihd < n_haloed_jproc; ihd++)
26435 if (ele_pt == f_haloed_ele_pt[jproc][ihd])
26438 index_haloed[jproc].push_back(ihd);
26449 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26452 const unsigned n_index_haloed_jproc = index_haloed[jproc].size();
26454 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26457 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
26460 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26473 template <
class ELEMENT>
26481 const unsigned nnew_nodes_on_domain= new_nodes_on_domain.size();
26482 const unsigned new_added_node_index =
26483 this->try_to_add_node_pt_load_balance(new_nodes_on_domain, nod_pt);
26486 if (new_added_node_index == nnew_nodes_on_domain)
26490 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26491 std::stringstream junk;
26492 junk <<
"Node needs to be constructed [size="
26501 get_required_nodal_information_load_balance_helper(f_halo_ele_pt,
26508 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26509 std::stringstream junk;
26510 junk <<
"Node was already added [size="
26520 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26532 template<
class ELEMENT>
26539 unsigned my_rank = this->communicator_pt()->my_rank();
26540 const unsigned nproc = this->communicator_pt()->nproc();
26545 unsigned n_val=nod_pt->
nvalue();
26547 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26551 unsigned n_dim=nod_pt->
ndim();
26555 if (this->Time_stepper_pt!=0)
26558 n_prev=this->Time_stepper_pt->ntstorage();
26567 const unsigned n_bnd = this->initial_shared_boundary_id();
26568 for (
unsigned bb=0;bb<n_bnd;bb++)
26573 original_boundaries.push_back(bb);
26578 const unsigned n_original_boundaries = original_boundaries.size();
26580 if (n_original_boundaries > 0)
26584 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26589 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26590 std::stringstream junk;
26591 junk <<
"Node is on "<< n_original_boundaries <<
" original boundaries";
26596 for (
unsigned i=0;
i<n_original_boundaries;
i++)
26599 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26600 std::stringstream junk;
26601 junk<<
"Node is on boundary "<<original_boundaries[
i]<<
" of "<< nb;
26614 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26621 bool node_on_shared_boundary =
false;
26624 const unsigned n_shd_bnd = this->nshared_boundaries(my_rank, iproc);
26625 for (
unsigned bb=0;bb<n_shd_bnd;bb++)
26628 unsigned i_bnd = this->shared_boundaries_ids(my_rank, iproc, bb);
26630 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26632 node_on_shared_boundary =
true;
26640 if (node_on_shared_boundary)
26643 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26650 for (
unsigned bb = 0; bb < n_shd_bnd; bb++)
26653 const unsigned i_bnd =
26654 this->shared_boundaries_ids(my_rank, iproc, bb);
26656 if (this->is_node_on_shared_boundary(i_bnd, nod_pt))
26658 shd_boundaries.push_back(i_bnd);
26663 const unsigned n_shd_bnd_is_on = shd_boundaries.size();
26666 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26667 std::stringstream junk;
26668 junk <<
"Node is on "<< n_shd_bnd_is_on <<
" shared boundaries";
26673 for (
unsigned i=0;
i<n_shd_bnd_is_on;
i++)
26676 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26677 std::stringstream junk;
26678 junk <<
"Node is on boundary " << shd_boundaries[
i] <<
" of " << nb;
26685 unsigned shared_boundary_id = shd_boundaries[0];
26687 const unsigned n_nodes_on_shared_boundary =
26688 nsorted_shared_boundary_node(shared_boundary_id);
26690 unsigned index_node_on_shared_boundary;
26693 bool found_index_node_on_shared_boundary =
false;
26696 for (
unsigned i = 0;
i < n_nodes_on_shared_boundary;
i++)
26699 Node* shared_node_pt =
26700 sorted_shared_boundary_node_pt(shared_boundary_id,
i);
26702 if (shared_node_pt == nod_pt)
26705 index_node_on_shared_boundary =
i;
26708 found_index_node_on_shared_boundary =
true;
26716 if (!found_index_node_on_shared_boundary)
26718 std::ostringstream error_message;
26720 <<
"The index of the node on boundary ("
26721 <<shared_boundary_id<<
") was not found.\n"
26722 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
","
26723 <<nod_pt->
x(1)<<
").\n";
26725 error_message.str(),
26726 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26727 OOMPH_EXCEPTION_LOCATION);
26732 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26733 std::stringstream junk2;
26734 junk2 <<
"Node index on boundary "<<
boundaries[0]<<
" is "
26735 <<index_node_on_shared_boundary;
26744 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26760 bool node_on_shared_boundary_with_other_processors =
false;
26762 unsigned nshared_boundaries_with_other_processors_have_node = 0;
26766 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26770 if (jproc != iproc)
26773 const unsigned n_jshd_bnd =
26774 this->nshared_boundaries(my_rank, jproc);
26776 for (
unsigned bb=0;bb<n_jshd_bnd;bb++)
26779 const unsigned j_shd_bnd =
26780 this->shared_boundaries_ids(my_rank, jproc, bb);
26782 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26790 node_on_shared_boundary_with_other_processors =
true;
26793 nshared_boundaries_with_other_processors_have_node++;
26804 if (node_on_shared_boundary_with_other_processors)
26807 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26815 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26816 std::stringstream junk;
26817 junk <<
"Number of other shared boundaries that the node is on: "
26818 << nshared_boundaries_with_other_processors_have_node;
26823 unsigned counter_shd_bnd_with_other_procs_have_node = 0;
26833 for (
unsigned jproc = 0; jproc < nproc; jproc++)
26837 if (jproc != iproc)
26841 const unsigned n_jshd_bnd =
26842 this->nshared_boundaries(my_rank, jproc);
26843 for (
unsigned bb = 0; bb < n_jshd_bnd; bb++)
26846 const unsigned j_shd_bnd =
26847 this->shared_boundaries_ids(my_rank, jproc, bb);
26849 if (this->is_node_on_shared_boundary(j_shd_bnd, nod_pt))
26852 other_processor_1.push_back(my_rank);
26854 other_processor_2.push_back(jproc);
26856 shd_bnd_ids.push_back(j_shd_bnd);
26859 counter_shd_bnd_with_other_procs_have_node++;
26870 const unsigned n_other_processors = other_processor_1.size();
26872 for (
unsigned i = 0;
i < n_other_processors;
i++)
26875 unsigned shd_bnd_id = shd_bnd_ids[
i];
26877 const unsigned n_nodes_on_shd_bnd =
26878 nsorted_shared_boundary_node(shd_bnd_id);
26881 bool found_index_node_on_shared_boundary =
false;
26883 for (
unsigned i = 0;
i < n_nodes_on_shd_bnd;
i++)
26886 Node* shared_node_pt =
26887 sorted_shared_boundary_node_pt(shd_bnd_id,
i);
26889 if (shared_node_pt == nod_pt)
26895 indexes.push_back(
i);
26898 found_index_node_on_shared_boundary =
true;
26906 if (!found_index_node_on_shared_boundary)
26908 std::ostringstream error_message;
26910 <<
"The index of the node on boundary ("
26911 <<shd_bnd_id<<
"), shared by other processors\nwas not found.\n"
26912 <<
"The node coordinates are ("<<nod_pt->
x(0)<<
","
26913 <<nod_pt->
x(1)<<
").\n";
26915 error_message.str(),
26916 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26917 OOMPH_EXCEPTION_LOCATION);
26926 if (counter_shd_bnd_with_other_procs_have_node !=
26927 nshared_boundaries_with_other_processors_have_node)
26929 std::ostringstream error_message;
26931 <<
"The number of shared boundaries where the node is on "
26932 <<
"is different:\n"
26933 <<
"nshared_boundaries_with_other_processors_have_node: ("
26934 << nshared_boundaries_with_other_processors_have_node
26936 <<
"counter_shd_bnd_with_other_procs_have_node: ("
26937 << counter_shd_bnd_with_other_procs_have_node
26940 error_message.str(),
26941 "RefineableTriangleMesh::get_required_nodal_information_helper()",
26942 OOMPH_EXCEPTION_LOCATION);
26948 for (
unsigned i = 0;
i < n_other_processors;
i++)
26951 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26952 std::stringstream junk1;
26953 junk1 <<
"Processor where the other shared boundary "
26954 <<
"has the node: " << other_processor_1[
i];
26959 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26960 std::stringstream junk2;
26961 junk2 <<
"Processor where the other shared boundary "
26962 <<
"has the node: " << other_processor_2[
i];
26967 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26968 std::stringstream junk3;
26969 junk3 <<
"Other shared boundary id where the node is on"
26975 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
26976 std::stringstream junk4;
26977 junk4 <<
"Node index on other shared boundary "
26989 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27022 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27025 const unsigned n_halo_jproc = f_halo_ele_pt[jproc].size();
27027 for (
unsigned jh = 0; jh < n_halo_jproc; jh++)
27031 const unsigned n_node = halo_ele_pt->
nnode();
27033 for (
unsigned n = 0;
n < n_node;
n++)
27036 if (nod_pt == halo_ele_pt->
node_pt(
n))
27038 halo_element_number[jproc].push_back(jh);
27039 halo_node_number_in_halo_element[jproc].push_back(
n);
27055 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27059 const unsigned n_jproc_halo_ele_node_is_on =
27060 halo_element_number[jproc].size();
27063 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27064 std::stringstream junk5;
27065 junk5 <<
"Node is on " << n_jproc_halo_ele_node_is_on <<
" halo "
27066 <<
"elements with " << jproc <<
"-th processor";
27072 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27075 const unsigned halo_element_index = halo_element_number[jproc][
i];
27077 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27078 std::stringstream junk6;
27079 junk6 <<
"Halo element index is ("<<halo_element_index
27080 <<
") with processor ("<<jproc<<
")";
27084 const unsigned node_index = halo_node_number_in_halo_element[jproc][
i];
27086 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27087 std::stringstream junk7;
27088 junk7 <<
"The node index on the halo element index is ("
27105 bool on_halo_element_with_iproc_processor =
false;
27106 if (halo_element_number[iproc].size() > 0)
27108 on_halo_element_with_iproc_processor =
true;
27112 if (!node_on_shared_boundary && !on_halo_element_with_iproc_processor)
27128 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27133 unsigned n_ref_val=alg_nod_pt->
nref_value();
27135 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27138 for (
unsigned i_ref_val=0;i_ref_val<n_ref_val;i_ref_val++)
27146 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27149 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
27157 unsigned found_geom_object=0;
27158 for (
unsigned i_list=0;i_list<n_geom_list;i_list++)
27162 found_geom_object=i_list;
27166 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27174 if (solid_nod_pt!=0)
27177 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
27179 for (
unsigned t=0;
t<n_prev;
t++)
27188 const unsigned nvalues_solid_node = values_solid_node.size();
27190 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27191 std::stringstream junk;
27192 junk <<
"Number of values solid node: "
27193 << nvalues_solid_node;
27196 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
27203 for (
unsigned i_val=0;i_val<n_val;i_val++)
27205 for (
unsigned t=0;
t<n_prev;
t++)
27212 for (
unsigned idim=0;idim<n_dim;idim++)
27214 for (
unsigned t=0;
t<n_prev;
t++)
27230 template <
class ELEMENT>
27235 &received_old_haloed_element_pt,
27239 &other_proc_shd_bnd_node_pt,
27244 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27246 <<
" Bool: New element needs to be constructed "
27265 new_elements_on_domain.push_back(f_el_pt);
27268 this->add_element_load_balance_helper(iproc,
27269 received_old_haloed_element_pt,
27273 unsigned n_node=f_el_pt->
nnode();
27274 for (
unsigned j=0;j<n_node;j++)
27276 Node* new_nod_pt=0;
27279 add_received_node_load_balance_helper(new_nod_pt,
27281 received_old_haloed_element_pt,
27282 new_nodes_on_domain,
27283 other_proc_shd_bnd_node_pt,
27286 node_name_to_global_index,
27287 global_shared_node_pt);
27292 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27295 <<
" Index of existing element "
27314 template<
class ELEMENT>
27319 &received_old_haloed_element_pt,
27323 const unsigned nproc = this->communicator_pt()->nproc();
27325 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27327 <<
" Bool: Element is associated to a boundary "
27333 const unsigned is_on_original_boundary =
27335 if (is_on_original_boundary == 1)
27337 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27340 <<
" How many boundaries are associated with the element "
27345 const unsigned nassociated_boundaries =
27349 for (
unsigned b = 0; b < nassociated_boundaries; b++)
27351 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27354 <<
" Boundary associated to the element "
27360 const unsigned bnd =
27363 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27366 <<
" Face index of the element "
27372 const unsigned face_index =
27377 this->Boundary_element_pt[bnd].push_back(ele_pt);
27378 this->Face_index_at_boundary[bnd].push_back(face_index);
27383 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27385 <<
" Bool: Element is associated to a boundary-region "
27393 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27396 <<
" How many boundaries-regions are associated with the element "
27401 const unsigned nassociated_boundaries_and_regions =
27404 for (
unsigned br = 0; br < nassociated_boundaries_and_regions; br++)
27406 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27409 <<
" Boundary associated to the element "
27414 const unsigned bnd =
27417 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27420 <<
" Region associated to the element "
27425 const unsigned region =
27428 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27431 <<
" Face index of the element in boundary-region "
27435 const unsigned face_index =
27440 this->Boundary_region_element_pt[bnd][region].push_back(ele_pt);
27441 this->Face_index_region_at_boundary[bnd][region].push_back(face_index);
27451 if (is_on_original_boundary != 0)
27453 std::ostringstream error_message;
27455 <<
"The current element is not on an original boundary, this should\n"
27456 <<
"be indicated by a zero flag. However, the read value for\n"
27457 <<
"that flag is ("<<is_on_original_boundary<<
").\n\n";
27459 error_message.str(),
27460 "RefineableTriangleMesh::add_element_load_balance_helper()",
27461 OOMPH_EXCEPTION_LOCATION);
27466 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27468 <<
" Bool: Element is associated to a shared boundary "
27474 const unsigned is_on_shared_boundary =
27476 if (is_on_shared_boundary == 3)
27478 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27481 <<
" How many shared boundaries are associated with the element "
27487 const unsigned nassociated_shared_boundaries =
27491 for (
unsigned b = 0; b < nassociated_shared_boundaries; b++)
27493 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27496 <<
" Shared boundary associated to the element "
27500 const unsigned bnd =
27503 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27506 <<
" Face index of the element associated to the shared boundary "
27511 const unsigned face_index =
27514 this->add_shared_boundary_element(bnd, ele_pt);
27515 this->add_face_index_at_shared_boundary(bnd, face_index);
27523 if (is_on_shared_boundary != 0)
27525 std::ostringstream error_message;
27527 <<
"The current element is not on a shared boundary, this should\n"
27528 <<
"be indicated by a zero flag. However, the read value for\n"
27529 <<
"that flag is ("<<is_on_shared_boundary<<
").\n\n";
27531 error_message.str(),
27532 "RefineableTriangleMesh::add_element_load_balance_helper()",
27533 OOMPH_EXCEPTION_LOCATION);
27542 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27544 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27546 <<
" Bool: Number of haloed indexes of the element with the "
27547 << jproc <<
" processor: "
27552 const unsigned n_index_haloed_jproc =
27555 for (
unsigned ihd = 0; ihd < n_index_haloed_jproc; ihd++)
27557 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27559 <<
" Bool: The haloed element index with the "
27560 << jproc <<
" processor: "
27564 const unsigned haloed_index =
27568 received_old_haloed_element_pt[iproc][jproc][haloed_index] = ele_pt;
27579 template <
class ELEMENT>
27586 &received_old_haloed_element_pt,
27589 std::map<unsigned, Node*> > > >
27590 &other_proc_shd_bnd_node_pt,
27592 unsigned& node_index,
27595 &global_node_names,
27597 &node_name_to_global_index,
27602 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27604 <<
" Bool: New node needs to be constructed "
27612 construct_new_node_load_balance_helper(new_nod_pt,
27614 received_old_haloed_element_pt,
27615 new_nodes_on_domain,
27616 other_proc_shd_bnd_node_pt,
27621 node_name_to_global_index,
27622 global_shared_node_pt);
27626 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27628 <<
" Index of existing halo node "
27635 new_nod_pt = new_nodes_on_domain[
27639 new_el_pt->
node_pt(node_index) = new_nod_pt;
27650 template<
class ELEMENT>
27656 &received_old_haloed_element_pt,
27659 &other_proc_shd_bnd_node_pt,
27660 unsigned& iproc,
unsigned& node_index,
27667 const unsigned nproc = this->communicator_pt()->nproc();
27669 const unsigned my_rank = this->communicator_pt()->my_rank();
27673 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27675 <<
" Number of values of external halo node "
27682 TimeStepper* time_stepper_pt=this->Time_stepper_pt;
27684 unsigned n_prev=time_stepper_pt->
ntstorage();
27688 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27690 <<
" Is the node on an original boundary "
27696 const unsigned node_on_original_boundaries =
27704 unsigned n_original_boundaries_node_is_on = 0;
27706 if (node_on_original_boundaries==2)
27709 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27711 <<
" Number of boundaries the node is on: "
27715 n_original_boundaries_node_is_on =
27719 original_boundaries_node_is_on.resize(n_original_boundaries_node_is_on);
27720 zeta_coordinates.resize(n_original_boundaries_node_is_on);
27722 for (
unsigned i=0;
i<n_original_boundaries_node_is_on;
i++)
27725 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27727 <<
" Node is on boundary "
27731 original_boundaries_node_is_on[
i] =
27733 zeta_coordinates[
i] =
27741 if (node_on_original_boundaries != 0)
27743 std::ostringstream error_message;
27745 <<
"The current node is not on an original boundary, this should\n"
27746 <<
"be indicated by a zero flag. However, the read value for\n"
27747 <<
"that flag is ("<<node_on_original_boundaries<<
").\n\n";
27749 error_message.str(),
27750 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27751 OOMPH_EXCEPTION_LOCATION);
27759 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27761 <<
" Is node on shared boundary? "
27765 const unsigned is_node_on_shared_boundary =
27767 if (is_node_on_shared_boundary == 1)
27770 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27772 <<
" Number of boundaries the node is on: "
27776 const unsigned n_shd_bnd_node_is_on =
27779 for (
unsigned i=0;
i<n_shd_bnd_node_is_on;
i++)
27782 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27784 <<
" Node is on boundary "
27788 shd_bnds_node_is_on[
i] =
27793 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27795 <<
" Index of node on boundary "
27800 unsigned node_index_on_shared_boundary =
27805 this->sorted_shared_boundary_node_pt(shd_bnds_node_is_on[0],
27806 node_index_on_shared_boundary);
27812 if (is_node_on_shared_boundary != 0)
27814 std::ostringstream error_message;
27816 <<
"The current node is not on a shared boundary, this should\n"
27817 <<
"be indicated by a zero flag. However, the read value for\n"
27818 <<
"that flag is ("<<is_node_on_shared_boundary<<
").\n\n";
27820 error_message.str(),
27821 "RefineableTriangleMesh::construct_new_halo_node_helper()",
27822 OOMPH_EXCEPTION_LOCATION);
27829 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27831 <<
" Is the node on shared boundaries with other processors "
27838 const unsigned is_the_node_in_shared_boundaries_with_other_processors =
27848 unsigned n_shd_bnd_with_other_procs_have_node = 0;
27851 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
27853 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27855 <<
" In how many shared boundaries with other "
27856 <<
"processors is the node "
27862 n_shd_bnd_with_other_procs_have_node =
27866 other_processor_1.resize(n_shd_bnd_with_other_procs_have_node);
27867 other_processor_2.resize(n_shd_bnd_with_other_procs_have_node);
27868 other_shared_boundaries.resize(n_shd_bnd_with_other_procs_have_node);
27869 other_indexes.resize(n_shd_bnd_with_other_procs_have_node);
27871 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
27873 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27875 <<
" Processor where the other shared boundary"
27881 other_processor_1[
i] =
27884 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27886 <<
" Processor where the other shared boundary"
27892 other_processor_2[
i] =
27895 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27897 <<
" Other shared boundary id where the node is on: "
27903 other_shared_boundaries[
i] =
27906 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27908 <<
" Node index on the other shared boundary "
27923 if (is_the_node_in_shared_boundaries_with_other_processors != 0)
27925 std::ostringstream error_message;
27927 <<
"The current node is not on a shared boundary with\n"
27928 <<
"other processors, this should be indicated by a zero flag.\n"
27929 <<
"However, the read value for that flag is ("
27930 <<is_the_node_in_shared_boundaries_with_other_processors<<
").\n\n";
27932 error_message.str(),
27933 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
27934 OOMPH_EXCEPTION_LOCATION);
27949 for (
unsigned jproc = 0; jproc < nproc; jproc++)
27951 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27953 <<
" The node is on "
27955 <<
" halo elements with " << jproc <<
" processor"
27960 const unsigned n_jproc_halo_ele_node_is_on =
27964 halo_element_number[jproc].resize(n_jproc_halo_ele_node_is_on);
27965 halo_node_number_in_halo_element[jproc].resize(n_jproc_halo_ele_node_is_on);
27970 for (
unsigned i = 0;
i < n_jproc_halo_ele_node_is_on;
i++)
27973 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27975 <<
" The halo element index where the node is on "
27980 const unsigned halo_ele_index =
27982 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
27984 <<
" The node index on the halo element where the node "
27989 const unsigned node_index_on_halo_ele =
27993 halo_element_number[jproc][
i] = halo_ele_index;
27995 halo_node_number_in_halo_element[jproc][
i] = node_index_on_halo_ele;
28004 std::set<Node*> set_haloed_node_pt;
28007 Node* haloed_node_pt = 0;
28013 bool on_haloed_element_with_iproc_processor =
false;
28014 if (halo_element_number[my_rank].size() > 0)
28018 on_haloed_element_with_iproc_processor =
true;
28021 const unsigned n_haloed_indexes = halo_element_number[my_rank].size();
28025 for (
unsigned i = 0;
i < n_haloed_indexes;
i++)
28028 const unsigned haloed_index = halo_element_number[my_rank][
i];
28030 const unsigned haloed_node_index =
28031 halo_node_number_in_halo_element[my_rank][
i];
28034 FiniteElement* tmp_haloed_ele_pt = f_haloed_ele_pt[iproc][haloed_index];
28036 Node* tmp_haloed_node_pt = tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28039 haloed_node_pt = tmp_haloed_node_pt;
28042 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28045 if (set_haloed_node_pt.size() > 1)
28047 std::ostringstream error_message;
28049 <<
"When adding the " << haloed_node_index <<
" node of the "
28050 << haloed_index <<
"-th haloed element\n"
28051 <<
"in the currrent processor with the " << iproc <<
" processor"
28052 <<
"it was found that\nthe node pointer is different from the other"
28053 <<
"instances of the node.\nIt means we have a repeated node."
28054 <<
"This are the node coordinates of the previous node instances\n"
28055 <<
"The last entry is for the just added node with a different node\n"
28057 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28058 it != set_haloed_node_pt.end(); it++)
28061 <<
"Node: ("<< (*it)->
x(0)<<
", "<<(*it)->x(1)<<
")\n";
28063 error_message <<
"\n";
28065 error_message.str(),
28066 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28067 OOMPH_EXCEPTION_LOCATION);
28077 bool found_on_haloed_element_with_other_processor =
false;
28080 for (
unsigned jproc = 0; jproc < iproc; jproc++)
28083 if (halo_element_number[jproc].size() > 0)
28086 const unsigned n_halo_indexes = halo_element_number[jproc].size();
28090 for (
unsigned i = 0;
i < n_halo_indexes;
i++)
28093 const unsigned haloed_index = halo_element_number[jproc][
i];
28095 const unsigned haloed_node_index =
28096 halo_node_number_in_halo_element[jproc][
i];
28100 std::map<unsigned,FiniteElement*>::iterator it_map =
28101 received_old_haloed_element_pt[jproc][iproc].find(haloed_index);
28103 if (it_map != received_old_haloed_element_pt[jproc][iproc].end())
28108 found_on_haloed_element_with_other_processor =
true;
28113 Node* tmp_haloed_node_pt =
28114 tmp_haloed_ele_pt->
node_pt(haloed_node_index);
28117 haloed_node_pt = tmp_haloed_node_pt;
28120 set_haloed_node_pt.insert(tmp_haloed_node_pt);
28123 if (set_haloed_node_pt.size() > 1)
28125 std::ostringstream error_message;
28127 <<
"When adding the " << haloed_node_index <<
" node of the "
28128 << haloed_index <<
"-th haloed element "
28129 <<
"of the " << jproc <<
" processor\nwith the "
28130 << iproc <<
" processor, it was found that\n"
28131 <<
"the node pointer is different from the other\n"
28132 <<
"instances of the node.\nThis means we have a repeated node.\n"
28133 <<
"These are the node coordinates of the previous node "
28135 <<
"The last entry is for the just added node with a different\n"
28136 <<
"node pointer\n";
28137 for (std::set<Node*>::iterator it = set_haloed_node_pt.begin();
28138 it != set_haloed_node_pt.end(); it++)
28141 <<
"Node: ("<< (*it)->
x(0)<<
", "<<(*it)->x(1)<<
")\n";
28143 error_message <<
"\n";
28145 error_message.str(),
28146 "RefineableTriangleMesh::construct_new_node_load_balance_helper()",
28147 OOMPH_EXCEPTION_LOCATION);
28165 if (on_haloed_element_with_iproc_processor ||
28166 found_on_haloed_element_with_other_processor)
28169 new_nod_pt = haloed_node_pt;
28177 if (is_node_on_shared_boundary == 1 ||
28178 (on_haloed_element_with_iproc_processor))
28183 if (node_on_original_boundaries==2)
28189 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28191 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28194 zeta[0] = zeta_coordinates[
i];
28196 original_boundaries_node_is_on[
i],zeta);
28202 new_nodes_on_domain.push_back(new_nod_pt);
28205 new_el_pt->
node_pt(node_index) = new_nod_pt;
28215 bool found_node_in_other_shared_boundaries =
false;
28224 bool build_node_as_boundary_node =
false;
28226 if (is_the_node_in_shared_boundaries_with_other_processors == 4)
28229 build_node_as_boundary_node =
true;
28236 const unsigned initial_shd_bnd_id = this->initial_shared_boundary_id();
28243 for (
unsigned i = 0;
i < n_shd_bnd_with_other_procs_have_node;
i++)
28245 unsigned oproc1 = other_processor_1[
i];
28246 unsigned oproc2 = other_processor_2[
i];
28250 if (oproc1 > oproc2)
28253 oproc1 = other_processor_2[
i];
28258 const unsigned shd_bnd_id =
28259 other_shared_boundaries[
i] - initial_shd_bnd_id;
28261 const unsigned index = other_indexes[
i];
28265 const unsigned n_nodes_on_other_processor =
28266 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].size();
28268 if (n_nodes_on_other_processor > 0)
28272 std::map<unsigned, Node*>::iterator it =
28273 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].
28278 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id].end())
28281 found_node_in_other_shared_boundaries =
true;
28283 Node* tmp_node_pt =
28284 other_proc_shd_bnd_node_pt[oproc1][oproc2][shd_bnd_id][index];
28285 found_node_pt.push_back(tmp_node_pt);
28295 if (found_node_in_other_shared_boundaries)
28298 const unsigned ntimes_node_found = found_node_pt.size();
28299 for (
unsigned j = 1; j < ntimes_node_found; j++)
28301 if (found_node_pt[j-1] != found_node_pt[j])
28303 std::ostringstream error_message;
28305 <<
"The instances of the node that was found to be on a\n"
28306 <<
"shared boundary with other processors are not the same,\n"
28307 <<
"the coordinates for the nodes are these:\n"
28308 <<
"(" << found_node_pt[j-1]->x(0) <<
", "
28309 << found_node_pt[j-1]->x(1) <<
")\n"
28310 <<
"(" << found_node_pt[j]->x(0) <<
", "
28311 << found_node_pt[j]->x(1) <<
")\n"
28312 <<
"Not be surprised if they are the same since the node is\n"
28315 error_message.str(),
28316 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28317 OOMPH_EXCEPTION_LOCATION);
28328 if (is_node_on_shared_boundary == 1)
28333 if (found_node_pt[0] != new_nod_pt)
28335 std::ostringstream error_message;
28337 <<
"The pointer of the node that was found to be on a\n"
28338 <<
"shared boundary with other processor(s) and the pointer\n"
28339 <<
"of the node on shared boundary with the receiver\n"
28340 <<
"processor (iproc) are not the same. This means we have a\n"
28341 <<
"repeated node)\n"
28342 <<
"The coordinates for the nodes are:\n"
28343 <<
"(" << found_node_pt[0]->x(0) <<
", "
28344 << found_node_pt[0]->x(1) <<
")\n"
28345 <<
"(" << new_nod_pt->
x(0) <<
", "
28346 << new_nod_pt->
x(1) <<
")\n"
28347 <<
"Not to be surprised if they are the same since the node is\n"
28350 error_message.str(),
28351 "RefineableTriangleMesh::construct_new_halo_node_helper()",
28352 OOMPH_EXCEPTION_LOCATION);
28361 new_nod_pt = found_node_pt[0];
28373 if (is_node_on_shared_boundary != 1 &&
28374 !on_haloed_element_with_iproc_processor)
28388 if (node_on_original_boundaries==2 || build_node_as_boundary_node)
28394 if (!found_node_in_other_shared_boundaries ||
28395 !found_on_haloed_element_with_other_processor)
28398 if (time_stepper_pt!=0)
28413 new_el_pt->
node_pt(node_index) = new_nod_pt;
28418 for (
unsigned i = 0;
i < n_original_boundaries_node_is_on;
i++)
28420 add_boundary_node(original_boundaries_node_is_on[
i], new_nod_pt);
28423 zeta[0] = zeta_coordinates[
i];
28425 original_boundaries_node_is_on[
i],zeta);
28435 if (!found_node_in_other_shared_boundaries ||
28436 !found_on_haloed_element_with_other_processor)
28439 if (time_stepper_pt!=0)
28441 new_nod_pt=new_el_pt->
construct_node(node_index, time_stepper_pt);
28452 new_el_pt->
node_pt(node_index) = new_nod_pt;
28464 new_nodes_on_domain.push_back(new_nod_pt);
28470 if (!found_node_in_other_shared_boundaries ||
28471 !found_on_haloed_element_with_other_processor)
28474 this->add_node_pt(new_nod_pt);
28484 if (new_alg_nod_pt!=0)
28493 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28495 <<
" Alg node update id "
28507 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28509 <<
" Alg node # of ref values "
28518 ref_value.resize(n_ref_val);
28519 for (
unsigned i_ref=0;i_ref<n_ref_val;i_ref++)
28532 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28534 <<
" Alg node # of geom objects "
28543 geom_object_pt.resize(n_geom_obj);
28544 for (
unsigned i_geom=0;i_geom<n_geom_obj;i_geom++)
28546 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28548 <<
" Alg node: geom object index "
28560 geom_object_pt[i_geom]=alg_mesh_pt->
28561 geom_object_list_pt(geom_index);
28568 if (!found_node_in_other_shared_boundaries ||
28569 !found_on_haloed_element_with_other_processor)
28574 (update_id,alg_mesh_pt,geom_object_pt,ref_value);
28588 if (!found_node_in_other_shared_boundaries ||
28589 !found_on_haloed_element_with_other_processor)
28595 if (macro_nod_pt!=0)
28605 geom_object_vector_pt=
28611 (node_index,s_in_macro_node_update_element);
28615 (new_el_pt,s_in_macro_node_update_element,
28616 geom_object_vector_pt);
28623 unsigned n_new_val=new_nod_pt->
nvalue();
28629 if (!found_node_in_other_shared_boundaries ||
28630 !found_on_haloed_element_with_other_processor)
28632 if (n_val>n_new_val)
28648 new std::map<unsigned, unsigned>;
28652 std::map<unsigned, unsigned>* map_pt=
28657 const unsigned id_face = 0;
28659 std::map<unsigned, unsigned>::const_iterator p=map_pt->find(id_face);
28662 if(p==map_pt->end())
28666 (*map_pt)[id_face] = n_new_val;
28669 new_nod_pt->
resize(n_val);
28679 if (solid_nod_pt!=0)
28682 for (
unsigned i_val=0;i_val<n_solid_val;i_val++)
28684 for (
unsigned t=0;
t<n_prev;
t++)
28693 if (!found_node_in_other_shared_boundaries ||
28694 !found_on_haloed_element_with_other_processor)
28697 set_value(
t, i_val, read_data);
28705 #ifdef ANNOTATE_REFINEABLE_TRIANGLE_MESH_COMMUNICATION_LOAD_BALANCE
28707 <<
" Number of values solid node: "
28711 const unsigned nvalues_solid_node =
28714 for (
unsigned i = 0;
i < nvalues_solid_node;
i++)
28716 values_solid_node[
i] =
28724 if (!found_node_in_other_shared_boundaries ||
28725 !found_on_haloed_element_with_other_processor)
28727 unsigned index = 0;
28736 for (
unsigned i_val=0;i_val<n_val;i_val++)
28738 for (
unsigned t=0;
t<n_prev;
t++)
28747 if (!found_node_in_other_shared_boundaries ||
28748 !found_on_haloed_element_with_other_processor)
28759 unsigned n_dim=new_nod_pt->
ndim();
28760 for (
unsigned idim=0;idim<n_dim;idim++)
28762 for (
unsigned t=0;
t<n_prev;
t++)
28771 if (!found_node_in_other_shared_boundaries ||
28772 !found_on_haloed_element_with_other_processor)
28775 new_nod_pt->
x(
t,idim) = read_data;
28788 if (n_shd_bnd_with_other_procs_have_node > 0 &&
28792 !found_node_in_other_shared_boundaries)
28801 this->update_other_proc_shd_bnd_node_helper(new_nod_pt,
28802 other_proc_shd_bnd_node_pt,
28805 other_shared_boundaries,
28808 node_name_to_global_index,
28809 global_shared_node_pt);
28815 #endif // #ifdef OOMPH_HAS_MPI
28823 template <
class ELEMENT>
28828 tmp_segment_nodes.clear();
28838 unsigned n_repeated_ele = 0;
28841 const unsigned n_regions = this->nregion();
28849 for (
unsigned rr = 0 ; rr < n_regions; rr++)
28851 const unsigned region_id =
28852 static_cast<unsigned>(this->Region_attribute[rr]);
28855 const unsigned nel_in_region =
28856 this->nboundary_element_in_region(b, region_id);
28859 unsigned nel_repeated_in_region = 0;
28863 if (nel_in_region > 0)
28867 bool repeated =
false;
28870 for (
unsigned e = 0;
e < nel_in_region;
e++)
28874 this->boundary_element_in_region_pt(b, region_id,
e);
28876 #ifdef OOMPH_HAS_MPI
28878 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
28889 this->face_index_at_boundary_in_region(b, region_id,
e);
28895 bulk_elem_pt, face_index);
28898 const unsigned n_nodes = tmp_ele_pt->
nnode();
28900 std::pair<Node*, Node*> tmp_pair =
28901 std::make_pair(tmp_ele_pt->
node_pt(0),
28902 tmp_ele_pt->
node_pt(n_nodes - 1));
28904 std::pair<Node*, Node*> tmp_pair_inverse =
28905 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
28909 unsigned n_done_nodes = done_nodes_pt.size();
28910 for (
unsigned l = 0; l < n_done_nodes; l++)
28912 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
28913 == done_nodes_pt[l])
28915 nel_repeated_in_region++;
28926 done_nodes_pt.push_back(tmp_pair);
28928 face_el_pt.push_back(tmp_ele_pt);
28944 nel += nel_in_region;
28947 n_repeated_ele += nel_repeated_in_region;
28958 nel = this->nboundary_element(b);
28965 bool repeated =
false;
28968 for (
unsigned e = 0;
e < nel;
e++)
28973 #ifdef OOMPH_HAS_MPI
28975 if (this->is_mesh_distributed() && bulk_elem_pt->
is_halo())
28985 int face_index = this->face_index_at_boundary(b,
e);
28990 bulk_elem_pt, face_index);
28993 const unsigned n_nodes = tmp_ele_pt->
nnode();
28995 std::pair<Node*, Node*> tmp_pair =
28996 std::make_pair(tmp_ele_pt->
node_pt(0),
28997 tmp_ele_pt->
node_pt(n_nodes - 1));
28999 std::pair<Node*, Node*> tmp_pair_inverse =
29000 std::make_pair(tmp_ele_pt->
node_pt(n_nodes - 1),
29004 unsigned n_done_nodes = done_nodes_pt.size();
29005 for (
unsigned l = 0; l < n_done_nodes; l++)
29007 if (tmp_pair == done_nodes_pt[l] || tmp_pair_inverse
29008 == done_nodes_pt[l])
29021 done_nodes_pt.push_back(tmp_pair);
29023 face_el_pt.push_back(tmp_ele_pt);
29042 nel -= n_repeated_ele;
29045 if (nel!=face_el_pt.size())
29047 std::ostringstream error_message;
29049 <<
"The independet counting of face elements ("<<nel<<
") for "
29050 <<
"boundary ("<<b<<
") is different\n"
29051 <<
"from the real number of face elements in the container ("
29052 << face_el_pt.size() <<
")\n";
29054 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29055 OOMPH_EXCEPTION_LOCATION);
29063 const unsigned nnon_halo_face_elements = nel;
29071 unsigned nsorted_face_elements = 0;
29075 std::map<FiniteElement*, bool> done_ele;
29080 std::map<FiniteElement*, bool> is_inverted;
29085 while(nsorted_face_elements < nnon_halo_face_elements)
29089 std::list<FiniteElement*> sorted_el_pt;
29093 bool found_initial_face_element =
false;
29098 unsigned iface = 0;
29099 #ifdef OOMPH_HAS_MPI
29100 if (this->is_mesh_distributed())
29102 for (iface = 0; iface < nel; iface++)
29104 ele_face_pt = face_el_pt[iface];
29106 if (!done_ele[ele_face_pt])
29111 found_initial_face_element =
true;
29114 nsorted_face_elements++;
29118 sorted_el_pt.push_back(ele_face_pt);
29120 done_ele[ele_face_pt] =
true;
29127 #endif // #ifdef OOMPH_HAS_MPI
29131 ele_face_pt = face_el_pt[0];
29134 found_initial_face_element =
true;
29137 nsorted_face_elements++;
29141 sorted_el_pt.push_back(ele_face_pt);
29143 done_ele[ele_face_pt] =
true;
29144 #ifdef OOMPH_HAS_MPI
29149 if (!found_initial_face_element)
29151 std::ostringstream error_message;
29153 <<
"Could not find an initial face element for the current segment\n";
29155 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29156 OOMPH_EXCEPTION_LOCATION);
29161 const unsigned nnod = ele_face_pt->
nnode();
29166 Node* right_node_pt = ele_face_pt->
node_pt(nnod - 1);
29170 bool face_element_added =
false;
29180 for (
unsigned iiface=iface;iiface<nel;iiface++)
29183 face_element_added =
false;
29186 ele_face_pt = face_el_pt[iiface];
29190 if (!done_ele[ele_face_pt])
29193 Node* local_left_node_pt = ele_face_pt->node_pt(0);
29194 Node* local_right_node_pt = ele_face_pt->node_pt(nnod - 1);
29197 if (left_node_pt == local_right_node_pt)
29199 left_node_pt = local_left_node_pt;
29200 sorted_el_pt.push_front(ele_face_pt);
29201 is_inverted[ele_face_pt] =
false;
29202 face_element_added =
true;
29205 else if (left_node_pt == local_left_node_pt)
29207 left_node_pt = local_right_node_pt;
29208 sorted_el_pt.push_front(ele_face_pt);
29209 is_inverted[ele_face_pt] =
true;
29210 face_element_added =
true;
29213 else if (right_node_pt == local_left_node_pt)
29215 right_node_pt = local_right_node_pt;
29216 sorted_el_pt.push_back(ele_face_pt);
29217 is_inverted[ele_face_pt] =
false;
29218 face_element_added =
true;
29221 else if (right_node_pt == local_right_node_pt)
29223 right_node_pt = local_left_node_pt;
29224 sorted_el_pt.push_back(ele_face_pt);
29225 is_inverted[ele_face_pt] =
true;
29226 face_element_added =
true;
29229 if (face_element_added)
29232 done_ele[ele_face_pt] =
true;
29233 nsorted_face_elements++;
29241 }
while(face_element_added &&
29242 (nsorted_face_elements < nnon_halo_face_elements));
29245 segment_sorted_ele_pt.push_back(sorted_el_pt);
29250 const unsigned nsegments = segment_sorted_ele_pt.size();
29253 if (nnon_halo_face_elements > 0 && nsegments == 0)
29255 std::ostringstream error_message;
29257 <<
"The number of segments is zero, but the number of nonhalo\n"
29258 <<
"elements is: (" << nnon_halo_face_elements <<
")\n";
29260 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29261 OOMPH_EXCEPTION_LOCATION);
29270 tmp_segment_nodes.resize(nsegments);
29272 for (
unsigned is = 0; is < nsegments; is++)
29275 if (segment_sorted_ele_pt[is].size() == 0)
29277 std::ostringstream error_message;
29279 <<
"The (" << is <<
")-th segment has no elements\n";
29281 "RefineableTriangleMesh::get_boundary_segment_nodes_helper()",
29282 OOMPH_EXCEPTION_LOCATION);
29287 FiniteElement* first_ele_pt = segment_sorted_ele_pt[is].front();
29290 const unsigned nnod = first_ele_pt->
nnode();
29294 if (is_inverted[first_ele_pt])
29296 first_node_pt = first_ele_pt->node_pt(nnod-1);
29300 tmp_segment_nodes[is].push_back(first_node_pt);
29303 for (std::list<FiniteElement*>::iterator it =
29304 segment_sorted_ele_pt[is].begin();
29305 it != segment_sorted_ele_pt[is].end(); it++)
29311 Node* last_node_pt = 0;
29314 if (!is_inverted[ele_pt])
29316 last_node_pt = ele_pt->node_pt(nnod-1);
29320 last_node_pt = ele_pt->node_pt(0);
29324 tmp_segment_nodes[is].push_back(last_node_pt);
29333 for (
unsigned e = 0;
e < nel;
e++)
29335 delete face_el_pt[
e];
29347 template <
class ELEMENT>
29359 double min_angle=compute_area_target(elem_error,
29365 bool quantised_areas=
true;
29366 if (quantised_areas)
29368 unsigned n=target_area.size();
29369 double total_area=0;
29375 #ifdef OOMPH_HAS_MPI
29376 if (this->is_mesh_distributed())
29380 double sub_area = 0.0;
29383 for (
unsigned e=0;
e<
n;
e++)
29389 sub_area+=ele_pt->
size();
29397 MPI_Allreduce(&sub_area, &total_area, 1, MPI_DOUBLE, MPI_SUM,
29398 comm_pt->mpi_comm());
29402 for (
unsigned e=0;
e<
n;
e++)
29404 total_area+=this->finite_element_pt(
e)->size();
29410 #else // #ifdef OOMPH_HAS_MPI
29411 for (
unsigned e=0;
e<
n;
e++)
29413 total_area+=this->finite_element_pt(
e)->size();
29415 #endif // #ifdef OOMPH_HAS_MPI
29417 for (
unsigned e=0;
e<
n;
e++)
29420 unsigned(ceil(log(target_area[
e]/total_area)/log(1.0/3.0)))-1;
29421 double new_target_area=total_area*pow(1.0/3.0,
int(
level));
29422 target_area[
e]=new_target_area;
29432 unsigned n=target_area.size();
29433 double max_area=0.0;
29434 double min_area=DBL_MAX;
29435 for (
unsigned e=0;
e<
n;
e++)
29437 if (target_area[
e]>max_area) max_area=target_area[
e];
29438 if (target_area[
e]<min_area) min_area=target_area[
e];
29453 oomph_info <<
"Maximum target area: " << max_area << std::endl;
29454 oomph_info <<
"Minimum target area: " << min_area << std::endl;
29455 oomph_info <<
"Number of elements to be refined: "
29456 << this->Nrefined << std::endl;
29457 oomph_info <<
"Number of elements to be unrefined: "
29458 << this->Nunrefined << std::endl;
29459 oomph_info <<
"Min. angle: " << min_angle << std::endl;
29461 double orig_max_area, orig_min_area;
29462 this->max_and_min_element_size(orig_max_area, orig_min_area);
29463 oomph_info <<
"Max./min. element size in original mesh: "
29464 << orig_max_area <<
" "
29465 << orig_min_area << std::endl;
29473 bool check_only=
true;
29474 bool outer_boundary_update_necessary=
false;
29475 bool inner_boundary_update_necessary=
false;
29476 bool inner_open_boundary_update_necessary=
false;
29480 const unsigned nouter=this->Outer_boundary_pt.size();
29482 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29485 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29487 outer_boundary_update_necessary=
29488 this->update_polygon_using_face_mesh(this->Outer_boundary_pt[i_outer],
29491 if (outer_boundary_update_necessary)
break;
29496 if (!outer_boundary_update_necessary)
29500 const unsigned nhole=this->Internal_polygon_pt.size();
29502 inner_boundary_update_necessary=
29503 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord,
29508 if (!inner_boundary_update_necessary)
29510 const unsigned n_open_polyline =
29511 this->Internal_open_curve_pt.size();
29513 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29515 inner_open_boundary_update_necessary=
29516 this->update_open_curve_using_face_mesh(
29517 this->Internal_open_curve_pt[
i], check_only);
29519 if (inner_open_boundary_update_necessary)
break;
29531 #ifdef OOMPH_HAS_MPI
29536 int adapt_this_processor = 0;
29537 if (this->is_mesh_distributed())
29540 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29541 (min_angle < min_permitted_angle())
29542 || (outer_boundary_update_necessary)
29543 || (inner_boundary_update_necessary)
29544 || (inner_open_boundary_update_necessary) )
29545 {adapt_this_processor = 1;}
29551 MPI_Allreduce(&adapt_this_processor, &adapt_all, 1, MPI_INT, MPI_SUM,
29552 comm_pt->mpi_comm());
29560 if ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ||
29561 (min_angle < min_permitted_angle()) || (outer_boundary_update_necessary)
29562 || (inner_boundary_update_necessary)
29563 || (inner_open_boundary_update_necessary) || (adapt_all) )
29565 if (! ( (Nrefined > 0) || (Nunrefined > max_keep_unrefined()) ) )
29568 if ( (outer_boundary_update_necessary)
29569 || (inner_boundary_update_necessary)
29570 || (inner_open_boundary_update_necessary) )
29573 <<
"Mesh regeneration triggered by inaccurate interface/surface\n"
29574 <<
"representation; setting Nrefined to number of elements.\n"
29575 <<
"outer_boundary_update_necessary : "
29576 << outer_boundary_update_necessary <<
"\n"
29577 <<
"inner_boundary_update_necessary : "
29578 << inner_boundary_update_necessary <<
"\n"
29579 <<
"inner_open_boundary_update_necessary: "
29580 << inner_open_boundary_update_necessary <<
"\n";
29581 Nrefined=nelement();
29586 <<
"Mesh regeneration triggered by min angle criterion;\n"
29587 <<
"setting Nrefined to number of elements.\n";
29588 Nrefined=nelement();
29595 #ifdef OOMPH_HAS_MPI
29596 else if (this->is_mesh_distributed() &&
29597 adapt_this_processor == 0 && adapt_all > 0)
29600 <<
"Mesh regeneration triggered by (" << adapt_all <<
") processor(s) "
29601 <<
"that require(s)\n adaptation\n";
29616 add_vertices_for_non_deletion();
29621 #ifdef OOMPH_HAS_MPI
29626 if (this->is_mesh_distributed())
29628 synchronize_shared_boundary_connections();
29630 #endif // #ifdef OOMPH_HAS_MPI
29641 if (this->is_automatic_creation_of_vertices_on_boundaries_allowed())
29644 unsigned nhole=this->Internal_polygon_pt.size();
29646 this->surface_remesh_for_inner_hole_boundaries(internal_point_coord);
29649 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29651 this->update_polygon_using_face_mesh(
29652 this->Outer_boundary_pt[i_outer]);
29657 unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29658 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29660 this->update_open_curve_using_face_mesh(
29661 this->Internal_open_curve_pt[
i]);
29671 const unsigned ninternal=this->Internal_polygon_pt.size();
29672 for (
unsigned i_internal = 0; i_internal < ninternal; i_internal++)
29674 this->update_polygon_using_elements_area(
29675 this->Internal_polygon_pt[i_internal], target_area);
29680 for (
unsigned i_outer = 0; i_outer < nouter; i_outer++)
29682 this->update_polygon_using_elements_area(
29683 this->Outer_boundary_pt[i_outer], target_area);
29688 const unsigned n_open_polyline = this->Internal_open_curve_pt.size();
29689 for (
unsigned i = 0;
i < n_open_polyline;
i++)
29691 this->update_open_curve_using_elements_area(
29692 this->Internal_open_curve_pt[
i], target_area);
29703 #ifdef OOMPH_HAS_MPI
29705 if (this->is_mesh_distributed())
29708 const unsigned my_rank = this->communicator_pt()->my_rank();
29711 const unsigned n_curves = this->nshared_boundary_curves(my_rank);
29713 for (
unsigned nc = 0; nc < n_curves; nc ++)
29716 this->update_shared_curve_using_elements_area(
29717 this->Shared_boundary_polyline_pt[my_rank][nc],
29743 const unsigned n_boundary = this->nboundary();
29745 const double t_start_first_stage_segments_connectivity =
29751 #ifdef OOMPH_HAS_MPI
29754 if (this->is_mesh_distributed())
29756 this->Assigned_segments_initial_zeta_values.clear();
29758 #endif // #ifdef OOMPH_HAS_MPI
29764 for(
unsigned b=0;b<n_boundary;++b)
29769 #ifdef OOMPH_HAS_MPI
29770 if (this->is_mesh_distributed())
29777 compute_boundary_segments_connectivity_and_initial_zeta_values(b);
29785 if(this->boundary_geom_object_pt(b)==0)
29787 this->
template setup_boundary_coordinates<ELEMENT>(b);
29793 #ifdef OOMPH_HAS_MPI
29794 if (this->is_mesh_distributed())
29799 this->synchronize_boundary_coordinates(b);
29808 const double t_total_first_stage_segments_connectivity =
29819 #ifdef OOMPH_HAS_MPI
29834 if (this->is_mesh_distributed())
29838 this->create_distributed_domain_representation(tmp_outer_polygons_pt,
29839 tmp_open_curves_pt);
29842 this->create_temporary_boundary_connections(tmp_outer_polygons_pt,
29843 tmp_open_curves_pt);
29859 restore_boundary_connections(resume_initial_connection_polyline_pt,
29860 resume_final_connection_polyline_pt);
29866 unsigned n_region = this->nregion();
29870 this->Regions_coordinates.begin();
29871 it!=this->Regions_coordinates.end(); ++it)
29877 unsigned region_id = it->first;
29880 oomph_info <<
"Region " << region_id <<
": "
29881 << it->second[0] <<
" " << it->second[1] <<
" ";
29884 unsigned n_region_element = this->nregion_element(region_id);
29885 if(n_region_element > 0)
29888 FiniteElement*
const elem_pt = this->region_element_pt(region_id,0);
29891 for(
unsigned n=0;
n<3;
n++)
29894 for(
unsigned i=0;
i<2;
i++) {centroid[
i] += nod_pt->
x(
i);}
29896 for(
unsigned i=0;
i<2;
i++) {centroid[
i] /= 3;}
29898 it->second = centroid;
29901 it->second[0] <<
" " << it->second[1] << std::endl;
29929 #ifdef OOMPH_HAS_MPI
29930 if (!this->is_mesh_distributed())
29934 closed_curve_pt.resize(nouter);
29935 for (
unsigned i = 0;
i < nouter;
i++)
29937 closed_curve_pt[
i] = this->Outer_boundary_pt[
i];
29941 const unsigned n_holes = this->Internal_polygon_pt.size();
29942 hole_pt.resize(n_holes);
29943 for (
unsigned i = 0;
i < n_holes;
i++)
29945 hole_pt[
i] = this->Internal_polygon_pt[
i];
29949 const unsigned n_open_curves = this->Internal_open_curve_pt.size();
29950 open_curves_pt.resize(n_open_curves);
29951 for (
unsigned i = 0;
i < n_open_curves;
i++)
29953 open_curves_pt[
i] = this->Internal_open_curve_pt[
i];
29959 #ifdef OOMPH_HAS_MPI
29964 const unsigned n_tmp_outer = tmp_outer_polygons_pt.size();
29965 closed_curve_pt.resize(n_tmp_outer);
29966 for (
unsigned i = 0;
i < n_tmp_outer;
i++)
29968 closed_curve_pt[
i] = tmp_outer_polygons_pt[
i];
29972 const unsigned n_open_curves = tmp_open_curves_pt.size();
29973 open_curves_pt.resize(n_open_curves);
29974 for (
unsigned i = 0;
i < n_open_curves;
i++)
29976 open_curves_pt[
i] = tmp_open_curves_pt[
i];
30006 this->Extra_holes_coordinates;
30010 this->Regions_coordinates;
30013 if (this->Use_attributes)
30019 if (!this->is_automatic_creation_of_vertices_on_boundaries_allowed())
30026 #ifdef OOMPH_HAS_MPI
30027 if (this->is_mesh_distributed())
30038 const double t_start_building_background_mesh =
30041 if (solid_mesh_pt!=0)
30044 (triangle_mesh_parameters, this->Time_stepper_pt);
30049 (triangle_mesh_parameters, this->Time_stepper_pt);
30052 if (Print_timings_level_adaptation>2)
30054 oomph_info <<
"CPU for building background mesh: "
30061 const double this_max_element_size = this->max_element_size();
30062 const double this_min_element_size = this->min_element_size();
30067 const double this_min_permitted_angle = this->min_permitted_angle();
30073 #ifdef OOMPH_HAS_MPI
30077 if (this->is_mesh_distributed())
30081 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30086 this->shared_boundary_overlaps_internal_boundary();
30091 this->shared_boundaries_ids();
30096 fill_boundary_elements_and_nodes_for_internal_boundaries();
30101 #endif // #ifdef OOMPH_HAS_MPI
30112 this->boundary_geom_object_pt();
30117 this->boundary_coordinate_limits();
30119 const double t_start_second_stage_segments_connectivity =
30122 for (
unsigned b=0;b<n_boundary;b++)
30127 #ifdef OOMPH_HAS_MPI
30128 if (this->is_mesh_distributed())
30133 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30144 tmp_new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30149 const double t_total_second_stage_segments_connectivity =
30156 for(
unsigned b=0;b<n_boundary;b++)
30158 this->snap_nodes_onto_boundary(tmp_new_mesh_pt,b);
30161 const double t_total_snap_nodes_bg_mesh=
30164 if (Print_timings_level_adaptation>2)
30166 oomph_info<<
"CPU for snapping nodes onto boundaries "
30167 <<
"(background mesh): "
30168 << t_total_snap_nodes_bg_mesh << std::endl;
30172 if(Mesh_update_fct_pt!=0)
30174 Mesh_update_fct_pt(tmp_new_mesh_pt);
30207 bool use_eulerian_coords=
false;
30208 if (solid_mesh_pt!=0)
30210 use_eulerian_coords=
true;
30214 #ifdef OOMPH_HAS_CGAL
30218 if (use_eulerian_coords)
30228 if (use_eulerian_coords)
30233 bin_dim[0]=Nbin_x_for_area_transfer;
30234 bin_dim[1]=Nbin_y_for_area_transfer;
30242 std::map<GeneralisedElement*,unsigned> element_number;
30243 unsigned nelem=this->nelement();
30244 for (
unsigned e=0;
e<nelem;
e++)
30246 element_number[this->element_pt(
e)]=
e;
30249 #ifndef OOMPH_HAS_CGAL
30259 sample_point_container_pt());
30260 if (bin_array_pt==0)
30263 "Sample point container has to be NonRefineableBinArray",
30264 OOMPH_CURRENT_FUNCTION,
30265 OOMPH_EXCEPTION_LOCATION);
30270 unsigned max_n_entry=0;
30271 unsigned min_n_entry=UINT_MAX;
30272 unsigned tot_n_entry=0;
30273 unsigned n_empty=0;
30275 tot_n_entry,n_empty);
30278 <<
" nbin:("<<n_bin<<
")"
30279 <<
" nempty:("<<n_empty<<
")"
30280 <<
" min:("<<min_n_entry<<
")"
30281 <<
" max:("<<max_n_entry<<
")"
30282 <<
" average entries:("
30283 << double(tot_n_entry)/double(n_bin)<<
")"
30289 oomph_info <<
"Going into diffusion bit...\n";
30291 oomph_info <<
"Back from diffusion bit...\n";
30299 unsigned max_n_entry=0;
30300 unsigned min_n_entry=UINT_MAX;
30301 unsigned tot_n_entry=0;
30302 unsigned n_empty=0;
30304 tot_n_entry,n_empty);
30307 <<
" nbin:("<<n_bin<<
")"
30308 <<
" nempty:("<<n_empty<<
")"
30309 <<
" min:("<<min_n_entry<<
")"
30310 <<
" max:("<<max_n_entry<<
")"
30311 <<
" average entries:("
30312 << double(tot_n_entry)/double(n_bin)<<
")"
30320 double t_total_map=0.0;
30323 unsigned counter_map = 0;
30333 const unsigned n_bin=bins_pt->size();
30338 bin_min_target_area.resize(n_bin);
30339 for (
unsigned u=0;
u<n_bin;
u++)
30341 bin_min_target_area[
u]=0.0;
30345 typedef std::map<unsigned,
30348 for (IT it=bins_pt->begin();it!=bins_pt->end();it++)
30351 unsigned ib=(*it).first;
30354 const unsigned n_ele_bin = (*it).second.size();
30357 for (
unsigned ee=0;ee<n_ele_bin;ee++)
30362 const unsigned ele_number = element_number[ele_pt];
30371 if (bin_min_target_area[ib]!=0)
30373 bin_min_target_area[ib]=
30374 std::min(bin_min_target_area[ib], target_area[ele_number]);
30378 bin_min_target_area[ib]=target_area[ele_number];
30385 oomph_info <<
"CPU for map[counter="<<counter_map<<
"]: "
30386 << t_total_map << std::endl;
30390 const bool output_bins=
false;
30393 unsigned length=bin_min_target_area.size();
30394 for (
unsigned u = 0;
u<length;
u++)
30397 << bin_min_target_area[
u]<<std::endl;
30408 #ifdef OOMPH_HAS_MPI
30410 unsigned n_ele_need_refinement = 0;
30414 double t_total_third_stage_segments_connectivity = 0.0;
30417 double t_total_transfer_target_areas = 0.0;
30420 double t_total_limit_target_areas = 0.0;
30423 double t_total_create_new_adapted_mesh = 0.0;
30426 double t_total_snap_nodes = 0.0;
30429 double t_total_wait_other_processors = 0.0;
30443 nelem=tmp_new_mesh_pt->
nelement();
30448 for (
unsigned e=0;
e<nelem;
e++)
30450 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(tmp_new_mesh_pt->
element_pt(
e));
30451 unsigned nint=el_pt->integral_pt()->nweight();
30452 for (
unsigned ipt=0;ipt<nint;ipt++)
30456 for(
unsigned i=0;
i<2;
i++)
30458 s[
i] = el_pt->integral_pt()->knot(ipt,
i);
30462 el_pt->interpolated_x(
s,x);
30469 unsigned max_sample_points=
30470 Max_sample_points_for_limited_locate_zeta_during_target_area_transfer;
30472 sample_point_container_pt())->
30473 limited_locate_zeta(x,max_sample_points,
30476 if (geom_obj_pt==0)
30478 std::stringstream error_message;
30480 <<
"Limited locate zeta failed for zeta = [ "
30481 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30483 OOMPH_CURRENT_FUNCTION,
30484 OOMPH_EXCEPTION_LOCATION);
30493 std::stringstream error_message;
30495 <<
"Cast to FE for GeomObject returned by limited locate zeta failed for zeta = [ "
30496 << x[0] <<
" " << x[1] <<
" ]. Makes no sense!\n";
30498 OOMPH_CURRENT_FUNCTION,
30499 OOMPH_EXCEPTION_LOCATION);
30505 double tg_area=target_area[element_number[fe_pt]];
30512 if (new_transferred_target_area[
e]!=0)
30514 new_transferred_target_area[
e]=
30515 std::min(new_transferred_target_area[
e],
30520 new_transferred_target_area[
e]=tg_area;
30531 bin_array_pt->
get_bin(x,bin_number);
30537 std::stringstream error_message;
30539 <<
"Very odd -- we're looking for a point[ "
30540 << x[0] <<
" " << x[1] <<
" ] that's not even \n"
30541 <<
"located within the bin boundaries.\n";
30543 "RefineableTriangleMesh::adapt()",
30544 OOMPH_EXCEPTION_LOCATION);
30552 if (new_transferred_target_area[
e]!=0)
30554 new_transferred_target_area[
e]=
30555 std::min(new_transferred_target_area[
e],
30556 bin_min_target_area[bin_number]);
30560 new_transferred_target_area[
e]=bin_min_target_area[bin_number];
30573 const bool output_target_areas=
false;
30574 if (output_target_areas)
30576 unsigned length=new_transferred_target_area.size();
30577 for (
unsigned u = 0;
u < length;
u++)
30580 << new_transferred_target_area[
u] << std::endl;
30583 oomph_info <<
"Time for loop over integration points in new mesh: "
30615 const double t_sub_total_transfer_target_areas =
30618 if (Print_timings_level_adaptation>2)
30621 const unsigned n_element = this->nelement();
30623 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30625 oomph_info <<
"CPU for transfer of target areas "
30626 <<
"[n_ele_old_mesh="
30627 << n_element <<
", n_ele_background_mesh="
30628 << n_element_background<<
"] (iter "<< iter <<
"): "
30629 << t_sub_total_transfer_target_areas<< std::endl;
30633 t_total_transfer_target_areas+=t_sub_total_transfer_target_areas;
30647 #ifdef OOMPH_HAS_MPI
30648 unsigned n_ele_need_refinement_iter = 0;
30660 const unsigned nel_new=tmp_new_mesh_pt->
nelement();
30662 for (
unsigned e=0;
e<nel_new;
e++)
30668 const double new_area=new_transferred_target_area[
e];
30671 std::ostringstream error_stream;
30672 error_stream <<
"This shouldn't happen! Element whose centroid is at "
30675 f_ele_pt->
node_pt(2)->
x(0))/3.0 <<
" "
30678 f_ele_pt->
node_pt(2)->
x(1))/3.0 <<
" "
30679 <<
" has no target area assigned\n";
30681 OOMPH_CURRENT_FUNCTION,
30682 OOMPH_EXCEPTION_LOCATION);
30690 new_target_area[
e]=new_area;
30691 if (new_target_area[
e]<f_ele_pt->
size()/3.0)
30693 new_target_area[
e]=f_ele_pt->
size()/3.0;
30713 #ifdef OOMPH_HAS_MPI
30715 n_ele_need_refinement_iter++;
30726 const double t_sub_total_limit_target_areas =
30730 t_total_limit_target_areas+=t_sub_total_limit_target_areas;
30732 if (Print_timings_level_adaptation>2)
30735 const unsigned n_element = this->nelement();
30737 const unsigned n_element_background = tmp_new_mesh_pt->
nelement();
30739 oomph_info <<
"CPU for limiting target areas "
30740 <<
"[n_ele_old_mesh="
30741 << n_element <<
", n_ele_background_mesh="
30742 << n_element_background<<
"] (iter "<< iter <<
"): "
30743 << t_sub_total_limit_target_areas<< std::endl;
30749 <<
"All area adjustments accommodated by max. permitted area"
30750 <<
" reduction \n";
30755 <<
"NOT all area adjustments accommodated by max. "
30756 <<
"permitted area reduction \n";
30769 const double t_start_create_new_adapted_mesh =
30773 if (solid_mesh_pt!=0)
30777 tmp_new_triangulateio,
30778 this->Time_stepper_pt,
30779 this->Use_attributes,
30780 this->Allow_automatic_creation_of_vertices_on_boundaries,
30781 this->communicator_pt());
30788 tmp_new_triangulateio,
30789 this->Time_stepper_pt,
30790 this->Use_attributes,
30791 this->Allow_automatic_creation_of_vertices_on_boundaries,
30792 this->communicator_pt());
30796 const double t_sub_total_create_new_adapted_mesh =
30800 t_total_create_new_adapted_mesh+=t_sub_total_create_new_adapted_mesh;
30802 if (Print_timings_level_adaptation>2)
30805 const unsigned n_element_new_adapted_mesh = new_mesh_pt->
nelement();
30807 oomph_info <<
"CPU for creation of new adapted mesh "
30808 << t_sub_total_create_new_adapted_mesh
30809 <<
"[nele="<<n_element_new_adapted_mesh
30810 <<
"] (iter "<< iter <<
"): "
30811 << t_sub_total_create_new_adapted_mesh << std::endl;
30814 #ifdef OOMPH_HAS_MPI
30825 if (this->nshared_boundary_overlaps_internal_boundary() > 0)
30830 this->shared_boundary_overlaps_internal_boundary();
30835 this->shared_boundaries_ids();
30840 fill_boundary_elements_and_nodes_for_internal_boundaries();
30845 #endif // #ifdef OOMPH_HAS_MPI
30853 this->boundary_geom_object_pt();
30858 this->boundary_coordinate_limits();
30860 const double t_start_third_stage_segments_connectivity =
30863 for (
unsigned b=0;b<n_boundary;b++)
30872 #ifdef OOMPH_HAS_MPI
30873 if (this->is_mesh_distributed())
30878 identify_boundary_segments_and_assign_initial_zeta_values(b,
this);
30889 new_mesh_pt->template setup_boundary_coordinates<ELEMENT>(b);
30894 t_total_third_stage_segments_connectivity+=
30901 for(
unsigned b=0;b<n_boundary;b++)
30903 this->snap_nodes_onto_boundary(new_mesh_pt,b);
30906 const double t_sub_total_snap_nodes_new_mesh =
30910 t_total_snap_nodes+=t_sub_total_snap_nodes_new_mesh;
30912 if (Print_timings_level_adaptation>2)
30914 oomph_info <<
"CPU for snapping nodes onto boundaries (new mesh) "
30915 <<
"(iter "<<iter<<
"): "
30916 << t_sub_total_snap_nodes_new_mesh<< std::endl;
30920 if (Mesh_update_fct_pt!=0)
30922 Mesh_update_fct_pt(new_mesh_pt);
30932 this->Time_stepper_pt,
false);
30938 delete tmp_new_mesh_pt;
30940 #ifdef OOMPH_HAS_MPI
30944 if (n_ele_need_refinement_iter == n_ele_need_refinement)
30948 n_ele_need_refinement = n_ele_need_refinement_iter;
30949 #endif // #ifdef OOMPH_HAS_MPI
30958 #ifdef OOMPH_HAS_MPI
30959 if (this->is_mesh_distributed())
30969 unsigned this_processor_requires_another_iteration = 1;
30972 if (done){this_processor_requires_another_iteration = 0;}
30973 int nproc_not_done = this_processor_requires_another_iteration;
30978 MPI_Allreduce(&this_processor_requires_another_iteration,
30980 MPI_UNSIGNED,MPI_SUM,comm_pt->mpi_comm());
30982 if (nproc_not_done > 0)
30984 oomph_info <<
"At least one processors requires further refinement. "
30985 <<
"Go for another iteration." << std::endl;
30991 const double t_sub_total_wait_other_processors =
30996 t_total_wait_other_processors+=t_sub_total_wait_other_processors;
30998 if (Print_timings_level_adaptation>2)
31000 oomph_info <<
"CPU for waiting other processors "
31001 <<
"(iter "<<iter<<
"): "
31002 << t_sub_total_wait_other_processors
31014 oomph_info <<
"Going for another iteration. Current iteration ("
31015 << iter <<
")" << std::endl;
31018 tmp_new_mesh_pt=new_mesh_pt;
31026 delete mesh_geom_obj_pt;
31028 oomph_info <<
"CPU for iterative generation of new mesh (TOTAL): "
31032 if (Print_timings_level_adaptation>1)
31034 oomph_info <<
"-- CPU for creating new adapted meshes (TOTAL): "
31035 << t_total_create_new_adapted_mesh << std::endl;
31037 oomph_info <<
"-- CPU for limiting target areas (TOTAL): "
31038 << t_total_limit_target_areas << std::endl;
31040 oomph_info <<
"-- CPU for transferring target areas (TOTAL): "
31041 << t_total_transfer_target_areas << std::endl;
31043 oomph_info <<
"-- CPU for waiting other processors (TOTAL): "
31044 << t_total_wait_other_processors << std::endl;
31056 if (!Disable_projection)
31062 if (Print_timings_projection)
31071 oomph_info <<
"About to begin projection.\n";
31080 #ifdef OOMPH_HAS_MPI
31081 if (this->is_mesh_distributed())
31089 Time* backed_up_time_pt = this->Time_stepper_pt->time_pt();
31099 project_problem_pt->
mesh_pt()=new_mesh_pt;
31104 if(!this->use_iterative_solver_for_projection())
31110 project_problem_pt->
project(
this);
31113 this->Time_stepper_pt->time_pt() = backed_up_time_pt;
31121 #endif // #ifdef OOMPH_HAS_MPI
31124 project_problem_pt->
mesh_pt()=new_mesh_pt;
31130 if(!this->use_iterative_solver_for_projection())
31136 project_problem_pt->
project(
this);
31140 if (Print_timings_projection)
31151 if (Print_timings_level_adaptation>1)
31154 const unsigned n_element = this->nelement();
31156 const unsigned n_element_new = new_mesh_pt->
nelement();
31157 oomph_info <<
"CPU for projection (in mesh adaptation) "
31158 <<
"[n_ele_old_mesh="<< n_element
31159 <<
", n_ele_new_mesh="<< n_element_new<<
"]: "
31160 << tt_projection << std::endl;
31165 #ifdef OOMPH_HAS_MPI
31166 if (this->is_mesh_distributed())
31170 unsigned n_this_element_new = n_element_new;
31171 unsigned n_max_element_new_global = 0;
31173 MPI_Reduce(&n_this_element_new, &n_max_element_new_global,
31174 1, MPI_UNSIGNED, MPI_MAX, 0,
31175 this->communicator_pt()->mpi_comm());
31178 double tt_this_projection = tt_projection;
31179 double tt_global_min_projection = 0.0;
31180 double tt_global_max_projection = 0.0;
31183 MPI_Reduce(&tt_this_projection, &tt_global_min_projection,
31184 1, MPI_DOUBLE, MPI_MIN, 0,
31185 this->communicator_pt()->mpi_comm());
31186 MPI_Reduce(&tt_this_projection, &tt_global_max_projection,
31187 1, MPI_DOUBLE, MPI_MAX, 0,
31188 this->communicator_pt()->mpi_comm());
31190 if (this->communicator_pt()->my_rank() == 0)
31192 oomph_info <<
"CPU for projection global (MIN): "
31193 << tt_global_min_projection << std::endl;
31194 oomph_info <<
"CPU for projection global (MAX) "
31195 <<
"[n_max_ele_new_global="
31196 << n_max_element_new_global<<
"]: "
31197 << tt_global_max_projection << std::endl;
31199 std::cerr <<
"CPU for projection global (MIN): "
31200 << tt_global_min_projection << std::endl;
31201 std::cerr <<
"CPU for projection global (MAX): "
31202 <<
"[n_max_ele_new_global="
31203 << n_max_element_new_global<<
"]: "
31204 << tt_global_max_projection << std::endl;
31209 #endif // #ifdef OOMPH_HAS_MPI
31216 oomph_info <<
"CPU for projection of solution onto new mesh: "
31221 delete project_problem_pt;
31226 oomph_info <<
"Projection disabled! The new mesh will contain zeros"
31237 unsigned nnod=nnode();
31238 for(
unsigned j=nnod;j>0;j--)
31240 delete Node_pt[j-1];
31243 unsigned nel=nelement();
31244 for(
unsigned e=nel;
e>0;
e--)
31246 delete Element_pt[
e-1];
31247 Element_pt[
e-1] = 0;
31252 nnod=new_mesh_pt->
nnode();
31253 Node_pt.resize(nnod);
31255 Element_pt.resize(nel);
31256 for(
unsigned j=0;j<nnod;j++)
31258 Node_pt[j] = new_mesh_pt->
node_pt(j);
31260 for(
unsigned e=0;
e<nel;
e++)
31267 unsigned nbound = 0;
31269 #ifdef OOMPH_HAS_MPI
31273 if (this->is_mesh_distributed())
31287 nbound = n_boundary;
31290 Boundary_element_pt.resize(nbound);
31291 Face_index_at_boundary.resize(nbound);
31292 Boundary_node_pt.resize(nbound);
31293 for (
unsigned b=0;b<nbound;b++)
31296 Boundary_element_pt[b].resize(nel);
31297 Face_index_at_boundary[b].resize(nel);
31298 for (
unsigned e=0;
e<nel;
e++)
31304 Boundary_node_pt[b].resize(nnod);
31305 for (
unsigned j=0;j<nnod;j++)
31312 unsigned n_region = new_mesh_pt->
nregion();
31317 this->Region_attribute.resize(n_region);
31318 for(
unsigned r=0;r<n_region;r++)
31322 unsigned r_id =
static_cast<unsigned>(this->Region_attribute[r]);
31325 this->Region_element_pt[r_id].resize(n_region_element);
31326 for(
unsigned e=0;
e<n_region_element;
e++)
31328 this->Region_element_pt[r_id][
e] =
31334 this->Boundary_region_element_pt.resize(nbound);
31335 this->Face_index_region_at_boundary.resize(nbound);
31338 for(
unsigned b=0;b<nbound;++b)
31340 for (
unsigned rr = 0 ; rr < n_region; rr++)
31343 unsigned r =
static_cast<unsigned>(this->Region_attribute[rr]);
31345 unsigned n_boundary_el_in_region =
31348 if(n_boundary_el_in_region > 0)
31351 this->Boundary_region_element_pt[b][r].
31352 resize(n_boundary_el_in_region);
31353 this->Face_index_region_at_boundary[b][r].
31354 resize(n_boundary_el_in_region);
31357 for(
unsigned e=0;
e<n_boundary_el_in_region;++
e)
31359 this->Boundary_region_element_pt[b][r][
e]
31361 this->Face_index_region_at_boundary[b][r][
e]
31375 #ifdef OOMPH_HAS_MPI
31376 if (this->is_mesh_distributed())
31381 if (this->is_mesh_distributed())
31383 this->Halo_node_pt.clear();
31384 this->Root_halo_element_pt.clear();
31386 this->Haloed_node_pt.clear();
31387 this->Root_haloed_element_pt.clear();
31389 this->External_halo_node_pt.clear();
31390 this->External_halo_element_pt.clear();
31392 this->External_haloed_node_pt.clear();
31393 this->External_haloed_element_pt.clear();
31398 this->reset_shared_boundary_elements_and_nodes();
31409 this->shared_boundaries_in_this_processor(my_rank_shared_boundaries_ids);
31412 const unsigned nmy_rank_shd_bnd = my_rank_shared_boundaries_ids.size();
31415 for (
unsigned i = 0;
i < nmy_rank_shd_bnd;
i++)
31418 const unsigned shd_bnd_id = my_rank_shared_boundaries_ids[
i];
31421 this->Boundary_element_pt[shd_bnd_id].clear();
31425 const unsigned tmp_nnodes =
31426 this->nshared_boundary_node(shd_bnd_id);
31427 for (
unsigned n = 0;
n < tmp_nnodes;
n++)
31429 Node* tmp_node_pt = this->boundary_node_pt(shd_bnd_id,
n);
31436 this->set_nboundary(n_boundary);
31440 this->sort_nodes_on_shared_boundaries();
31443 this->reset_halo_haloed_scheme();
31447 for (
unsigned b = 0; b < n_boundary; b++)
31449 if (this->boundary_geom_object_pt(b)!=0)
31452 this->set_nboundary_segment_node(b, nsegments);
31457 resume_boundary_connections(resume_initial_connection_polyline_pt,
31458 resume_final_connection_polyline_pt);
31462 #endif // #ifdef OOMPH_HAS_MPI
31469 this->snap_nodes_onto_geometric_objects();
31477 this->Triangulateio=
31485 delete new_mesh_pt;
31488 if (Print_timings_level_adaptation>2)
31492 oomph_info <<
"CPU for segments connectivity (first stage) [sec]: "
31493 << t_total_first_stage_segments_connectivity << std::endl;
31494 oomph_info <<
"CPU for segments connectivity (second stage) [sec]: "
31495 << t_total_second_stage_segments_connectivity << std::endl;
31496 oomph_info <<
"CPU for segments connectivity (third stage) [sec]: "
31497 << t_total_third_stage_segments_connectivity << std::endl;
31500 if (Print_timings_level_adaptation>1)
31502 const double t_total_segments_connectivity =
31503 t_total_first_stage_segments_connectivity +
31504 t_total_second_stage_segments_connectivity +
31505 t_total_third_stage_segments_connectivity;
31507 oomph_info <<
"CPU for segments connectivity (TOTAL) [sec]: "
31508 << t_total_segments_connectivity << std::endl;
31510 if (Print_timings_level_adaptation>2)
31513 oomph_info <<
"CPU for snapping nodes onto boundaries "
31515 << t_total_snap_nodes << std::endl;
31518 t_total_snap_nodes+=t_total_snap_nodes_bg_mesh;
31519 oomph_info <<
"CPU for snapping nodes onto boundaries (TOTAL): "
31520 << t_total_snap_nodes << std::endl;
31523 double max_area=0.0;
31524 double min_area=0.0;
31526 this->max_and_min_element_size(max_area, min_area);
31527 oomph_info <<
"Max/min element size in adapted mesh: "
31529 << min_area << std::endl;
31531 oomph_info <<
"CPU time for final bits [sec]: "
31537 oomph_info <<
"Not enough benefit in adaptation.\n";
31543 oomph_info <<
"CPU time for adaptation [sec]: "
31544 << CPU_for_adaptation << std::endl;
31549 #ifdef OOMPH_HAS_MPI
31550 if (this->is_mesh_distributed())
31555 const unsigned n_proc = comm_pt->nproc();
31556 if (Print_timings_level_adaptation>1 && n_proc>1)
31558 double global_min_CPU_for_adaptation = 0.0;
31559 double global_max_CPU_for_adaptation = 0.0;
31560 double global_average_CPU_for_adaptation = 0.0;
31563 MPI_Reduce(&CPU_for_adaptation, &global_min_CPU_for_adaptation,
31564 1, MPI_DOUBLE, MPI_MIN, 0, comm_pt->mpi_comm());
31565 MPI_Reduce(&CPU_for_adaptation, &global_max_CPU_for_adaptation,
31566 1, MPI_DOUBLE, MPI_MAX, 0, comm_pt->mpi_comm());
31567 MPI_Reduce(&CPU_for_adaptation, &global_average_CPU_for_adaptation,
31568 1, MPI_DOUBLE, MPI_SUM, 0, comm_pt->mpi_comm());
31571 const unsigned my_rank = comm_pt->my_rank();
31575 << global_min_CPU_for_adaptation << std::endl;
31577 << global_max_CPU_for_adaptation << std::endl;
31578 oomph_info <<
"CPU for adaptation (AVERAGE): "
31579 << global_average_CPU_for_adaptation/n_proc << std::endl;
31590 #endif // #ifdef OOMPH_HAS_MPI
31601 template<
class ELEMENT>
31606 Boundary_connections_pt.clear();
31613 std::set<unsigned> boundary_id_with_connections;
31620 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
31623 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31629 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31631 for (
unsigned p = 0; p < n_polyline; p++)
31641 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31645 boundary_id_with_connections.insert(bnd_id);
31648 const unsigned dst_bnd_id =
31653 boundary_id_with_connections.insert(dst_bnd_id);
31661 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31665 boundary_id_with_connections.insert(bnd_id);
31668 const unsigned dst_bnd_id =
31673 boundary_id_with_connections.insert(dst_bnd_id);
31686 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
31689 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
31695 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31697 for (
unsigned p = 0; p < n_polyline; p++)
31707 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31711 boundary_id_with_connections.insert(bnd_id);
31714 const unsigned dst_bnd_id =
31719 boundary_id_with_connections.insert(dst_bnd_id);
31727 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31731 boundary_id_with_connections.insert(bnd_id);
31734 const unsigned dst_bnd_id =
31739 boundary_id_with_connections.insert(dst_bnd_id);
31752 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
31755 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
31759 this->Internal_open_curve_pt[
i];
31763 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
31766 for (
unsigned p = 0; p < n_curve_section; p++)
31777 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31781 boundary_id_with_connections.insert(bnd_id);
31784 const unsigned dst_bnd_id =
31789 boundary_id_with_connections.insert(dst_bnd_id);
31797 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31801 boundary_id_with_connections.insert(bnd_id);
31804 const unsigned dst_bnd_id =
31809 boundary_id_with_connections.insert(dst_bnd_id);
31817 #ifdef OOMPH_HAS_MPI
31824 if (this->is_mesh_distributed())
31827 const unsigned my_rank = this->communicator_pt()->my_rank();
31830 const unsigned n_shared_curves =
31831 this->nshared_boundary_curves(my_rank);
31834 for (
unsigned i = 0;
i < n_shared_curves;
i ++)
31838 const unsigned n_polyline =
31839 this->nshared_boundary_polyline(my_rank,
i);
31843 for (
unsigned p = 0; p < n_polyline; p++)
31847 this->shared_boundary_polyline_pt(my_rank,
i, p);
31853 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31857 boundary_id_with_connections.insert(bnd_id);
31860 const unsigned dst_bnd_id =
31865 boundary_id_with_connections.insert(dst_bnd_id);
31873 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31877 boundary_id_with_connections.insert(bnd_id);
31880 const unsigned dst_bnd_id =
31885 boundary_id_with_connections.insert(dst_bnd_id);
31895 #endif // #ifdef OOMPH_HAS_MPI
31903 std::map<unsigned, Vector<Vector<Node*> > > bnd_sorted_segment_node_pt;
31906 for (std::set<unsigned>::iterator it =
31907 boundary_id_with_connections.begin();
31908 it != boundary_id_with_connections.end(); it++)
31911 const unsigned bnd_id = (*it);
31912 #ifdef OOMPH_HAS_MPI
31914 if (this->is_mesh_distributed())
31917 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
31919 if (bnd_id >= init_shd_bnd_id)
31927 get_shared_boundary_segment_nodes_helper(bnd_id,
31928 tmp_shared_nodes_pt);
31931 bnd_sorted_segment_node_pt[bnd_id] = tmp_shared_nodes_pt;
31942 get_boundary_segment_nodes_helper(bnd_id,
31943 tmp_boundary_nodes_pt);
31946 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31952 #endif // #ifdef OOMPH_HAS_MPI
31960 get_boundary_segment_nodes_helper(bnd_id,
31961 tmp_boundary_nodes_pt);
31964 bnd_sorted_segment_node_pt[bnd_id] = tmp_boundary_nodes_pt;
31978 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
31984 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
31986 for (
unsigned p = 0; p < n_polyline; p++)
31996 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
31999 const unsigned dst_bnd_id =
32003 const unsigned dst_chunk =
32008 bnd_sorted_segment_node_pt[bnd_id];
32012 bnd_sorted_segment_node_pt[dst_bnd_id];
32016 add_non_delete_vertices_from_boundary_helper(
32017 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32025 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32028 const unsigned dst_bnd_id =
32032 const unsigned dst_chunk =
32037 bnd_sorted_segment_node_pt[bnd_id];
32041 bnd_sorted_segment_node_pt[dst_bnd_id];
32045 add_non_delete_vertices_from_boundary_helper(
32046 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32058 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32064 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32066 for (
unsigned p = 0; p < n_polyline; p++)
32076 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32079 const unsigned dst_bnd_id =
32083 const unsigned dst_chunk =
32088 bnd_sorted_segment_node_pt[bnd_id];
32092 bnd_sorted_segment_node_pt[dst_bnd_id];
32096 add_non_delete_vertices_from_boundary_helper(
32097 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32105 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32108 const unsigned dst_bnd_id =
32112 const unsigned dst_chunk =
32117 bnd_sorted_segment_node_pt[bnd_id];
32121 bnd_sorted_segment_node_pt[dst_bnd_id];
32125 add_non_delete_vertices_from_boundary_helper(
32126 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32138 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32142 this->Internal_open_curve_pt[
i];
32146 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32149 for (
unsigned p = 0; p < n_curve_section; p++)
32160 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32163 const unsigned dst_bnd_id =
32167 const unsigned dst_chunk =
32172 bnd_sorted_segment_node_pt[bnd_id];
32176 bnd_sorted_segment_node_pt[dst_bnd_id];
32180 add_non_delete_vertices_from_boundary_helper(
32181 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32189 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32192 const unsigned dst_bnd_id =
32196 const unsigned dst_chunk =
32201 bnd_sorted_segment_node_pt[bnd_id];
32205 bnd_sorted_segment_node_pt[dst_bnd_id];
32209 add_non_delete_vertices_from_boundary_helper(
32210 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32218 #ifdef OOMPH_HAS_MPI
32225 if (this->is_mesh_distributed())
32228 const unsigned my_rank = this->communicator_pt()->my_rank();
32231 const unsigned n_shared_curves =
32232 this->nshared_boundary_curves(my_rank);
32235 for (
unsigned i = 0;
i < n_shared_curves;
i ++)
32239 const unsigned n_polyline =
32240 this->nshared_boundary_polyline(my_rank,
i);
32244 for (
unsigned p = 0; p < n_polyline; p++)
32248 this->shared_boundary_polyline_pt(my_rank,
i, p);
32254 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32257 const unsigned dst_bnd_id =
32261 const unsigned dst_chunk =
32266 bnd_sorted_segment_node_pt[bnd_id];
32270 bnd_sorted_segment_node_pt[dst_bnd_id];
32274 add_non_delete_vertices_from_boundary_helper(
32275 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32283 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32286 const unsigned dst_bnd_id =
32290 const unsigned dst_chunk =
32295 bnd_sorted_segment_node_pt[bnd_id];
32299 bnd_sorted_segment_node_pt[dst_bnd_id];
32303 add_non_delete_vertices_from_boundary_helper(
32304 src_bnd_node_pt, dst_bnd_node_pt, dst_bnd_id, dst_chunk);
32314 #endif // #ifdef OOMPH_HAS_MPI
32323 template<
class ELEMENT>
32328 const unsigned &dst_bnd_id,
const unsigned &dst_bnd_chunk)
32331 const unsigned n_seg = src_bound_segment_node_pt.size();
32333 for (
unsigned iseg = 0; iseg < n_seg; iseg++)
32336 const unsigned nnode = src_bound_segment_node_pt[iseg].size();
32338 Node* left_node_pt = src_bound_segment_node_pt[iseg][0];
32339 Node* right_node_pt = src_bound_segment_node_pt[iseg][nnode-1];
32342 const unsigned n_dst_seg = dst_bound_segment_node_pt.size();
32344 for (
unsigned jseg = 0; jseg < n_dst_seg; jseg++)
32347 const unsigned n_dst_node = dst_bound_segment_node_pt[jseg].size();
32350 for (
unsigned jnode = 0; jnode < n_dst_node; jnode++)
32354 Node* tmp_node_pt = dst_bound_segment_node_pt[jseg][jnode];
32357 if (tmp_node_pt == left_node_pt)
32361 vertex[0] = tmp_node_pt->
x(0);
32362 vertex[1] = tmp_node_pt->
x(1);
32368 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32376 else if (tmp_node_pt == right_node_pt)
32380 vertex[0] = tmp_node_pt->
x(0);
32381 vertex[1] = tmp_node_pt->
x(1);
32389 Boundary_connections_pt[dst_bnd_id].insert(vertex);
32404 #ifdef OOMPH_HAS_MPI
32410 template<
class ELEMENT>
32415 const unsigned nproc = this->communicator_pt()->nproc();
32417 const unsigned my_rank = this->communicator_pt()->my_rank();
32420 for (
unsigned jproc = 0; jproc < nproc; jproc++)
32425 const unsigned n_shd_bnd_jproc =
32426 this->nshared_boundaries(my_rank, jproc);
32430 if (jproc != my_rank && n_shd_bnd_jproc > 0)
32450 this->shared_boundaries_ids(my_rank, jproc);
32453 const unsigned n_shd_bnd_jproc = shd_bnd_ids.size();
32455 for (
unsigned ishd_bnd=0;ishd_bnd<n_shd_bnd_jproc;ishd_bnd++)
32458 const unsigned shd_bnd_id = shd_bnd_ids[ishd_bnd];
32461 this->boundary_polyline_pt(shd_bnd_id);
32466 std::set<Vector<double> > no_delete_vertex;
32469 const bool boundary_receive_connections =
32470 this->boundary_connections(shd_bnd_id, chunk,
32474 const unsigned n_non_delete_vertex = no_delete_vertex.size();
32477 if (boundary_receive_connections && n_non_delete_vertex > 0)
32480 shd_bnd_id_for_non_deletion.push_back(shd_bnd_id);
32482 chunk_for_non_deletion.push_back(chunk);
32484 number_vertices_non_deletion.push_back(n_non_delete_vertex);
32491 no_delete_vertex.begin();
32492 it != no_delete_vertex.end(); it++)
32496 tmp_vertices.push_back(vertex);
32500 vertices_for_non_deletion.push_back(tmp_vertices);
32518 MPI_Request request;
32524 const unsigned n_shd_bnd_with_non_delete_vertices =
32525 shd_bnd_id_for_non_deletion.size();
32528 const unsigned size_package = 3;
32530 const unsigned n_unsigned_data_to_send =
32531 n_shd_bnd_with_non_delete_vertices*size_package;
32541 for (
unsigned i=0;
i<n_shd_bnd_with_non_delete_vertices;
i++)
32544 flat_package_unsigned_send[j++] =
32545 shd_bnd_id_for_non_deletion[
i];
32547 flat_package_unsigned_send[j++] =
32548 chunk_for_non_deletion[
i];
32550 flat_package_unsigned_send[j++] =
32551 number_vertices_non_deletion[
i];
32553 const unsigned n_vertices_non_deletion =
32554 number_vertices_non_deletion[
i];
32557 for (
unsigned h=0;h<n_vertices_non_deletion;h++)
32559 flat_package_double_send.push_back(
32560 vertices_for_non_deletion[
i][h][0]);
32561 flat_package_double_send.push_back(
32562 vertices_for_non_deletion[
i][h][1]);
32568 int send_proc = jproc;
32569 int recv_proc = jproc;
32570 unsigned send_count_unsigned_values = n_unsigned_data_to_send;
32571 unsigned send_count_double_values = flat_package_double_send.size();
32576 MPI_Isend(&send_count_unsigned_values,1,MPI_UNSIGNED,
32577 send_proc,1,comm_pt->mpi_comm(),&request);
32579 unsigned receive_count_unsigned_values=0;
32580 MPI_Recv(&receive_count_unsigned_values,1,MPI_UNSIGNED,
32581 recv_proc,1,comm_pt->mpi_comm(),&status);
32583 MPI_Wait(&request,MPI_STATUS_IGNORE);
32586 if (send_count_unsigned_values!=0)
32588 MPI_Isend(&flat_package_unsigned_send[0],
32589 send_count_unsigned_values,MPI_UNSIGNED,
32590 send_proc,2,comm_pt->mpi_comm(),&request);
32594 if (receive_count_unsigned_values!=0)
32596 flat_package_unsigned_recv.resize(receive_count_unsigned_values);
32597 MPI_Recv(&flat_package_unsigned_recv[0],
32598 receive_count_unsigned_values,
32599 MPI_UNSIGNED,recv_proc,2,comm_pt->mpi_comm(),&status);
32604 if (send_count_unsigned_values!=0)
32606 MPI_Wait(&request,MPI_STATUS_IGNORE);
32611 MPI_Isend(&send_count_double_values,1,MPI_UNSIGNED,
32612 send_proc,1,comm_pt->mpi_comm(),&request);
32614 unsigned receive_count_double_values=0;
32615 MPI_Recv(&receive_count_double_values,1,MPI_UNSIGNED,
32616 recv_proc,1,comm_pt->mpi_comm(),&status);
32618 MPI_Wait(&request,MPI_STATUS_IGNORE);
32621 if (send_count_double_values!=0)
32623 MPI_Isend(&flat_package_double_send[0],
32624 send_count_double_values,MPI_DOUBLE,
32625 send_proc,2,comm_pt->mpi_comm(),&request);
32629 if (receive_count_double_values!=0)
32631 flat_package_double_recv.resize(receive_count_double_values);
32632 MPI_Recv(&flat_package_double_recv[0],
32633 receive_count_double_values,
32634 MPI_DOUBLE,recv_proc,2,comm_pt->mpi_comm(),&status);
32639 if (send_count_double_values!=0)
32641 MPI_Wait(&request,MPI_STATUS_IGNORE);
32669 for (
unsigned i=0;
i<receive_count_unsigned_values;
i+=3)
32672 const unsigned recv_shd_bnd_id =
32673 flat_package_unsigned_recv[
i];
32674 recv_shd_bnd_id_for_non_deletion.push_back(recv_shd_bnd_id);
32676 const unsigned recv_chunk =
32677 flat_package_unsigned_recv[
i+1];
32678 recv_chunk_for_non_deletion.push_back(recv_chunk);
32680 const unsigned recv_num_vertices =
32681 flat_package_unsigned_recv[
i+2];
32682 recv_number_vertices_non_deletion.push_back(recv_num_vertices);
32687 for (
unsigned h=0;h<recv_num_vertices;h++)
32690 tmp_vertex[0] = flat_package_double_recv[j++];
32691 tmp_vertex[1] = flat_package_double_recv[j++];
32693 temp_recv_vertices.push_back(tmp_vertex);
32697 recv_vertices_for_non_deletion.push_back(temp_recv_vertices);
32712 const unsigned n_recv_shd_bnd_id_for_non_deletion =
32713 recv_shd_bnd_id_for_non_deletion.size();
32716 for (
unsigned i=0;
i<n_recv_shd_bnd_id_for_non_deletion;
i++)
32719 const unsigned shd_bnd_id =
32720 recv_shd_bnd_id_for_non_deletion[
i];
32722 unsigned chunk = recv_chunk_for_non_deletion[
i];
32729 const unsigned n_vertices =
32730 recv_number_vertices_non_deletion[
i];
32732 for (
unsigned h=0;h<n_vertices;h++)
32736 vertex[0] = recv_vertices_for_non_deletion[
i][h][0];
32737 vertex[1] = recv_vertices_for_non_deletion[
i][h][1];
32742 Boundary_connections_pt[shd_bnd_id].insert(vertex);
32753 #endif // #ifdef OOMPH_HAS_MPI
32760 template<
class ELEMENT>
32770 dummy_resume_initial_connection_polyline_pt.clear();
32771 dummy_resume_final_connection_polyline_pt.clear();
32775 const unsigned init_shd_bnd_id = this->initial_shared_boundary_id();
32793 const unsigned n_outer_boundaries = tmp_outer_polygons_pt.size();
32796 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32802 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32804 for (
unsigned p = 0; p < n_polyline; p++)
32811 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32814 if (bnd_id < init_shd_bnd_id)
32817 restore_polyline_connections_helper(
32819 dummy_resume_initial_connection_polyline_pt,
32820 dummy_resume_final_connection_polyline_pt);
32837 const unsigned n_open_boundaries = tmp_open_curves_pt.size();
32840 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32847 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32850 for (
unsigned p = 0; p < n_curve_section; p++)
32858 const unsigned bnd_id = tmp_polyline_pt->
boundary_id();
32861 if (bnd_id < init_shd_bnd_id)
32864 restore_polyline_connections_helper(
32866 dummy_resume_initial_connection_polyline_pt,
32867 dummy_resume_final_connection_polyline_pt);
32887 template<
class ELEMENT>
32893 resume_initial_connection_polyline_pt.clear();
32894 resume_final_connection_polyline_pt.clear();
32905 const unsigned n_outer_boundaries = this->Outer_boundary_pt.size();
32908 for (
unsigned i = 0;
i < n_outer_boundaries;
i++)
32914 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32916 for (
unsigned p = 0; p < n_polyline; p++)
32923 restore_polyline_connections_helper(
32925 resume_initial_connection_polyline_pt,
32926 resume_final_connection_polyline_pt);
32937 const unsigned n_internal_boundaries = this->Internal_polygon_pt.size();
32940 for (
unsigned i = 0;
i < n_internal_boundaries;
i++)
32946 const unsigned n_polyline = tmp_polygon_pt->
npolyline();
32948 for (
unsigned p = 0; p < n_polyline; p++)
32955 restore_polyline_connections_helper(
32957 resume_initial_connection_polyline_pt,
32958 resume_final_connection_polyline_pt);
32969 const unsigned n_open_boundaries = this->Internal_open_curve_pt.size();
32972 for (
unsigned i = 0;
i < n_open_boundaries;
i++)
32976 this->Internal_open_curve_pt[
i];
32980 const unsigned n_curve_section = tmp_open_curve_pt->
ncurve_section();
32983 for (
unsigned p = 0; p < n_curve_section; p++)
32991 restore_polyline_connections_helper(
32993 resume_initial_connection_polyline_pt,
32994 resume_final_connection_polyline_pt);
33010 template<
class ELEMENT>
33028 const unsigned dst_bnd_id_initial =
33037 #ifdef OOMPH_HAS_MPI
33038 if (this->is_mesh_distributed())
33041 const unsigned init_shd_bnd_id =
33042 this->initial_shared_boundary_id();
33044 if (dst_bnd_id_initial >= init_shd_bnd_id)
33047 const unsigned bnd_id = polyline_pt->
boundary_id();
33048 std::ostringstream error_message;
33050 <<
"INITIAL VERTEX CONNECTION\n"
33051 <<
"The current original boundary is trying to connect to a\n"
33052 <<
"shared boundary, this is not allowed. In this case the\n"
33053 <<
"shared boundary should be the one that connects with the\n"
33054 <<
"original boundary\n"
33055 <<
"The current original boundary (" << bnd_id <<
") is marked\n"
33056 <<
"to have a connection at the\nINITIAL vertex ("
33057 << src_vertex_coordinates_initial[0] <<
","
33058 << src_vertex_coordinates_initial[1] <<
")\n"
33059 <<
"with the shared boundary ("<< dst_bnd_id_initial <<
")\n"
33060 <<
"This is the list of vertices on the shared destination boundary\n";
33064 this->boundary_polyline_pt(dst_bnd_id_initial);
33066 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33068 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33073 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33076 error_message.str(),
33077 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33078 OOMPH_EXCEPTION_LOCATION);
33082 #endif // #ifdef OOMPH_HAS_MPI
33084 #endif // #ifdef PARANOID
33088 bool found_vertex_on_dst_boundary_initial =
false;
33092 unsigned sub_poly_to_connect = 0;
33095 unsigned n_vertex_connection_initial = 0;
33100 bool connecting_to_an_split_boundary =
false;
33104 bool connecting_to_an_overlaped_boundary =
false;
33106 #ifdef OOMPH_HAS_MPI
33107 if (this->is_mesh_distributed())
33112 if (this->boundary_was_splitted(dst_bnd_id_initial))
33114 connecting_to_an_split_boundary =
true;
33123 if (connecting_to_an_split_boundary)
33127 const unsigned n_sub_poly =
33128 this->nboundary_subpolylines(dst_bnd_id_initial);
33132 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33135 boundary_marked_as_shared_boundary(dst_bnd_id_initial, ii))
33139 connecting_to_an_overlaped_boundary =
true;
33151 boundary_marked_as_shared_boundary(dst_bnd_id_initial, 0))
33154 connecting_to_an_overlaped_boundary =
true;
33160 #endif // #ifdef OOMPH_HAS_MPI
33165 if (!(connecting_to_an_split_boundary ||
33166 connecting_to_an_overlaped_boundary))
33170 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_initial);
33180 if (!connecting_to_an_split_boundary)
33184 if (!connecting_to_an_overlaped_boundary)
33188 found_vertex_on_dst_boundary_initial =
33189 this->get_connected_vertex_number_on_destination_polyline(
33190 poly_to_connect_pt,
33191 src_vertex_coordinates_initial,
33192 n_vertex_connection_initial);
33205 #ifdef OOMPH_HAS_MPI
33213 this->boundary_subpolylines(dst_bnd_id_initial);
33216 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33218 if (nsub_poly <= 1)
33220 std::ostringstream error_message;
33222 <<
"The boundary (" << dst_bnd_id_initial <<
") was "
33223 <<
"marked to be splitted but\n"
33224 <<
"there are only ("<<nsub_poly<<
") polylines to "
33225 <<
"represent it.\n";
33227 error_message.str(),
33228 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33229 OOMPH_EXCEPTION_LOCATION);
33240 if (!connecting_to_an_overlaped_boundary)
33248 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33251 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33253 found_vertex_on_dst_boundary_initial =
33254 this->get_connected_vertex_number_on_destination_polyline(
33255 poly_to_connect_pt,
33256 src_vertex_coordinates_initial,
33257 n_vertex_connection_initial);
33261 if (found_vertex_on_dst_boundary_initial)
33265 sub_poly_to_connect = isub;
33281 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33286 boundary_marked_as_shared_boundary(dst_bnd_id_initial, isub))
33289 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33292 found_vertex_on_dst_boundary_initial =
33293 this->get_connected_vertex_number_on_destination_polyline(
33294 poly_to_connect_pt,
33295 src_vertex_coordinates_initial,
33296 n_vertex_connection_initial);
33299 if (found_vertex_on_dst_boundary_initial)
33303 sub_poly_to_connect = isub;
33314 #endif // #ifdef OOMPH_HAS_MPI
33318 if (!found_vertex_on_dst_boundary_initial)
33321 #ifdef OOMPH_HAS_MPI
33322 if (this->is_mesh_distributed())
33332 resume_initial_connection_polyline_pt.push_back(polyline_pt);
33339 #endif // #ifdef OOMPH_HAS_MPI
33344 const unsigned bnd_id = polyline_pt->
boundary_id();
33345 std::ostringstream error_message;
33347 <<
"INITIAL VERTEX CONNECTION\n"
33348 <<
"It was not possible to find the associated "
33349 <<
"vertex number on the destination boundary\n"
33350 <<
"The current boundary (" << bnd_id <<
") is marked to have"
33351 <<
"a connection at the\nINITIAL vertex ("
33352 << src_vertex_coordinates_initial[0] <<
","
33353 << src_vertex_coordinates_initial[1] <<
")\n"
33354 <<
"with boundary ("<< dst_bnd_id_initial <<
")\n"
33355 <<
"This is the list of vertices on the destination boundary\n";
33359 this->boundary_polyline_pt(dst_bnd_id_initial);
33361 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33363 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33368 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33371 error_message.str(),
33372 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33373 OOMPH_EXCEPTION_LOCATION);
33383 n_vertex_connection_initial;
33387 sub_poly_to_connect;
33401 const unsigned dst_bnd_id_final =
33405 const unsigned tmp_n_vertices = polyline_pt->
nvertex();
33412 #ifdef OOMPH_HAS_MPI
33413 if (this->is_mesh_distributed())
33416 const unsigned init_shd_bnd_id =
33417 this->initial_shared_boundary_id();
33419 if (dst_bnd_id_final >= init_shd_bnd_id)
33422 const unsigned bnd_id = polyline_pt->
boundary_id();
33423 std::ostringstream error_message;
33425 <<
"FINAL VERTEX CONNECTION\n"
33426 <<
"The current original boundary is trying to connect to a\n"
33427 <<
"shared boundary, this is not allowed. In this case the\n"
33428 <<
"shared boundary should be the one that connects with the\n"
33429 <<
"original boundary\n"
33430 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33431 <<
"a connection at the\nFINAL vertex ("
33432 << src_vertex_coordinates_final[0] <<
","
33433 << src_vertex_coordinates_final[1] <<
")\n"
33434 <<
"with boundary ("<< dst_bnd_id_final <<
")\n"
33435 <<
"This is the list of vertices on the destination boundary\n";
33439 this->boundary_polyline_pt(dst_bnd_id_final);
33441 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33443 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33447 <<
"Vertex#("<<
i<<
"): ("
33448 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33451 error_message.str(),
33452 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33453 OOMPH_EXCEPTION_LOCATION);
33457 #endif // #ifdef OOMPH_HAS_MPI
33459 #endif // #ifdef PARANOID
33463 bool found_vertex_on_dst_boundary_final =
false;
33467 unsigned sub_poly_to_connect = 0;
33470 unsigned n_vertex_connection_final = 0;
33475 bool connecting_to_an_split_boundary =
false;
33479 bool connecting_to_an_overlaped_boundary =
false;
33481 #ifdef OOMPH_HAS_MPI
33482 if (this->is_mesh_distributed())
33487 if (this->boundary_was_splitted(dst_bnd_id_final))
33489 connecting_to_an_split_boundary =
true;
33498 if (connecting_to_an_split_boundary)
33502 const unsigned n_sub_poly =
33503 this->nboundary_subpolylines(dst_bnd_id_final);
33507 for (
unsigned ii =0; ii < n_sub_poly; ii++)
33510 boundary_marked_as_shared_boundary(dst_bnd_id_final, ii))
33514 connecting_to_an_overlaped_boundary =
true;
33526 boundary_marked_as_shared_boundary(dst_bnd_id_final, 0))
33529 connecting_to_an_overlaped_boundary =
true;
33535 #endif // #ifdef OOMPH_HAS_MPI
33540 if (!(connecting_to_an_split_boundary ||
33541 connecting_to_an_overlaped_boundary))
33545 poly_to_connect_pt = this->boundary_polyline_pt(dst_bnd_id_final);
33555 if (!connecting_to_an_split_boundary)
33559 if (!connecting_to_an_overlaped_boundary)
33563 found_vertex_on_dst_boundary_final =
33564 this->get_connected_vertex_number_on_destination_polyline(
33565 poly_to_connect_pt,
33566 src_vertex_coordinates_final,
33567 n_vertex_connection_final);
33580 #ifdef OOMPH_HAS_MPI
33588 this->boundary_subpolylines(dst_bnd_id_final);
33591 const unsigned nsub_poly = tmp_vector_subpolylines.size();
33593 if (nsub_poly <= 1)
33595 std::ostringstream error_message;
33597 <<
"The boundary (" << dst_bnd_id_final <<
") was "
33598 <<
"marked to be splitted but\n"
33599 <<
"there are only ("<<nsub_poly<<
") polylines to "
33600 <<
"represent it.\n";
33602 error_message.str(),
33603 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33604 OOMPH_EXCEPTION_LOCATION);
33615 if (!connecting_to_an_overlaped_boundary)
33623 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33626 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33628 found_vertex_on_dst_boundary_final =
33629 this->get_connected_vertex_number_on_destination_polyline(
33630 poly_to_connect_pt,
33631 src_vertex_coordinates_final,
33632 n_vertex_connection_final);
33636 if (found_vertex_on_dst_boundary_final)
33640 sub_poly_to_connect = isub;
33656 for (
unsigned isub = 0; isub < nsub_poly; isub++)
33661 boundary_marked_as_shared_boundary(dst_bnd_id_final, isub))
33664 poly_to_connect_pt = tmp_vector_subpolylines[isub];
33667 found_vertex_on_dst_boundary_final =
33668 this->get_connected_vertex_number_on_destination_polyline(
33669 poly_to_connect_pt,
33670 src_vertex_coordinates_final,
33671 n_vertex_connection_final);
33674 if (found_vertex_on_dst_boundary_final)
33678 sub_poly_to_connect = isub;
33689 #endif // #ifdef OOMPH_HAS_MPI
33693 if (!found_vertex_on_dst_boundary_final)
33696 #ifdef OOMPH_HAS_MPI
33697 if (this->is_mesh_distributed())
33707 resume_final_connection_polyline_pt.push_back(polyline_pt);
33714 #endif // #ifdef OOMPH_HAS_MPI
33719 const unsigned bnd_id = polyline_pt->
boundary_id();
33720 std::ostringstream error_message;
33722 <<
"FINAL VERTEX CONNECTION\n"
33723 <<
"It was not possible to find the associated "
33724 <<
"vertex number on the destination boundary\n"
33725 <<
"The current boundary (" << bnd_id <<
") is marked to have "
33726 <<
"a connection at the\nFINAL vertex ("
33727 << src_vertex_coordinates_final[0] <<
","
33728 << src_vertex_coordinates_final[1] <<
")\n"
33729 <<
"with boundary ("<< dst_bnd_id_final <<
")\n"
33730 <<
"This is the list of vertices on the destination boundary\n";
33734 this->boundary_polyline_pt(dst_bnd_id_final);
33736 const unsigned n_vertex_dst_boundary = dst_polyline->
nvertex();
33738 for (
unsigned i = 0;
i < n_vertex_dst_boundary;
i++)
33742 <<
"Vertex#("<<
i<<
"): ("
33743 << current_vertex[0] <<
", " << current_vertex[1] <<
")\n";
33746 error_message.str(),
33747 "RefineableTriangleMesh::restore_polyline_connections_helper()",
33748 OOMPH_EXCEPTION_LOCATION);
33757 n_vertex_connection_final;
33761 sub_poly_to_connect;
33777 template<
class ELEMENT>
33784 const unsigned n_initial_poly =
33785 resume_initial_connection_polyline_pt.size();
33788 for (
unsigned p = 0; p < n_initial_poly; p++)
33792 resume_initial_connection_polyline_pt[p];
33799 const unsigned n_final_poly =
33800 resume_final_connection_polyline_pt.size();
33803 for (
unsigned p = 0; p < n_final_poly; p++)
33807 resume_final_connection_polyline_pt[p];
33813 resume_initial_connection_polyline_pt.clear();
33814 resume_final_connection_polyline_pt.clear();
33822 template<
class ELEMENT>
33826 const unsigned &dst_bnd_id,
33827 unsigned &vertex_number)
33830 bool found_associated_vertex_number =
false;
33834 this->boundary_polyline_pt(dst_bnd_id);
33836 const unsigned n_vertices = dst_polyline->
nvertex();
33840 for (
unsigned i = 0;
i < n_vertices;
i++)
33847 (vertex_coordinates[0] - current_vertex[0])*
33848 (vertex_coordinates[0] - current_vertex[0])
33850 (vertex_coordinates[1] - current_vertex[1])*
33851 (vertex_coordinates[1] - current_vertex[1]);
33853 error = sqrt(error);
33859 found_associated_vertex_number =
true;
33865 return found_associated_vertex_number;
33878 template<
class ELEMENT>
33881 const bool& check_only)
33889 if (this->is_mesh_distributed() && !check_only)
33891 std::stringstream error_message;
33893 <<
"The updating of polygons of a distributed mesh can ONLY be\n"
33894 <<
"performed using the element's area associated to the halo(ed)\n"
33896 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
33897 <<
"option if you are working with a distributed mesh, OR\n"
33898 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
33899 <<
"if the mesh is marked as distributed\n\n";
33901 OOMPH_CURRENT_FUNCTION,
33902 OOMPH_EXCEPTION_LOCATION);
33908 bool unrefinement_was_performed=
false;
33909 bool refinement_was_performed=
false;
33910 bool max_length_applied =
false;
33913 const unsigned n_polyline = polygon_pt->
npolyline();
33919 get_face_mesh_representation(polygon_pt,face_mesh_pt);
33927 for(
unsigned p=0;p<n_polyline;p++)
33932 std::set<Vector<double> > vertex_nodes;
33941 unsigned n_face_element = face_mesh_pt[p]->nelement();
33942 for(
unsigned e=0;
e<n_face_element;++
e)
33946 #ifdef OOMPH_HAS_MPI
33948 if (this->is_mesh_distributed() && el_pt->
is_halo()) {
continue;}
33951 unsigned n_node = el_pt->
nnode();
33957 vertex_coord[0] = bound_left[0];
33960 for(
unsigned i=0;
i<2;
i++)
33962 vertex_coord[
i+1] = el_pt->
node_pt(0)->
x(
i);
33964 vertex_nodes.insert(vertex_coord);
33970 get_coordinates_on_boundary(bound,bound_right);
33971 vertex_coord[0] = bound_right[0];
33974 for(
unsigned i=0;
i<2;
i++)
33976 vertex_coord[
i+1] = el_pt->
node_pt(n_node-1)->
x(
i);
33978 vertex_nodes.insert(vertex_coord);
33983 unsigned n_poly_vertex = vertex_nodes.size();
33986 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
33987 it!=vertex_nodes.end();++it)
33989 tmp_vector_vertex_node[count].resize(3);
33990 tmp_vector_vertex_node[count][0] = (*it)[0];
33991 tmp_vector_vertex_node[count][1] = (*it)[1];
33992 tmp_vector_vertex_node[count][2] = (*it)[2];
33997 unsigned n_vertex=tmp_vector_vertex_node.size();
34001 double unrefinement_tolerance=
34007 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34009 unrefinement_was_performed =
34010 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34011 unrefinement_tolerance, check_only);
34016 if (check_only && unrefinement_was_performed)
34020 for(
unsigned p=0;p<n_polyline;p++)
34022 face_mesh_pt[p]->flush_node_storage();
34023 delete face_mesh_pt[p];
34032 n_vertex=tmp_vector_vertex_node.size();
34037 double refinement_tolerance=
34039 if (refinement_tolerance>0.0 && n_vertex >= 2)
34041 refinement_was_performed =
34042 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34043 refinement_tolerance, check_only);
34048 if (check_only && refinement_was_performed)
34052 for(
unsigned p=0;p<n_polyline;p++)
34054 face_mesh_pt[p]->flush_node_storage();
34055 delete face_mesh_pt[p];
34065 n_vertex=tmp_vector_vertex_node.size();
34071 if (maximum_length > 0.0 && n_vertex >= 2)
34073 max_length_applied =
34074 apply_max_length_constraint(face_mesh_pt[p],
34075 tmp_vector_vertex_node,
34080 if (check_only && max_length_applied)
34084 for(
unsigned p=0;p<n_polyline;p++)
34086 face_mesh_pt[p]->flush_node_storage();
34087 delete face_mesh_pt[p];
34096 n_vertex=tmp_vector_vertex_node.size();
34099 for(
unsigned i=0;
i<n_vertex;
i++)
34101 vector_vertex_node[
i].resize(2);
34102 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
34103 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
34106 #ifdef OOMPH_HAS_MPI
34110 if (!this->is_mesh_distributed())
34113 if ( (p > 0) && !check_only )
34117 unsigned n_prev_vertex =
34119 final_vertex_of_previous_segment =
34121 vertex_coordinate(n_prev_vertex-1);
34123 unsigned prev_seg_boundary_id =
34128 double error = 0.0;
34129 for(
unsigned i=0;
i<2;
i++)
34131 const double dist =
34132 final_vertex_of_previous_segment[
i] -
34133 (*vector_vertex_node.begin())[
i];
34134 error += dist*dist;
34136 error = sqrt(error);
34144 double rev_error = 0.0;
34145 for(
unsigned i=0;
i<2;
i++)
34147 const double dist =
34148 final_vertex_of_previous_segment[
i] -
34149 (*--vector_vertex_node.end())[
i];
34150 rev_error += dist*dist;
34152 rev_error = sqrt(rev_error);
34167 initial_vertex_of_previous_segment =
34169 vertex_coordinate(0);
34171 unsigned prev_seg_boundary_id =
34176 double error = 0.0;
34177 for(
unsigned i=0;
i<2;
i++)
34179 const double dist =
34180 initial_vertex_of_previous_segment[
i] -
34181 (*vector_vertex_node.begin())[
i];
34182 error += dist*dist;
34184 error = sqrt(error);
34192 double rev_error = 0.0;
34193 for(
unsigned i=0;
i<2;
i++)
34195 const double dist =
34196 initial_vertex_of_previous_segment[
i] -
34197 (*--vector_vertex_node.end())[
i];
34198 rev_error += dist*dist;
34200 rev_error = sqrt(rev_error);
34206 std::ostringstream error_stream;
34208 <<
"The distance between the first node of the current\n"
34209 <<
"line segment (boundary " << bound <<
") and either end of "
34210 <<
"the previous line segment\n"
34211 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
34212 <<
"the desired tolerance " <<
34214 <<
"This suggests that the polylines defining the polygonal\n"
34215 <<
"representation are not properly ordered.\n"
34216 <<
"Fail on last vertex of polyline: ("
34217 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
34218 << bound <<
").\nThis should have failed when first trying to "
34219 <<
"construct the\npolygon.\n";
34221 OOMPH_CURRENT_FUNCTION,
34222 OOMPH_EXCEPTION_LOCATION);
34229 std::reverse(vector_vertex_node.begin(),
34230 vector_vertex_node.end());
34244 std::ostringstream error_stream;
34246 <<
"The distance between the first node of the current\n"
34247 <<
"line segment (boundary " << bound <<
") and either end of "
34248 <<
"the previous line segment\n"
34249 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
34250 <<
"desired tolerance " <<
34252 <<
"This suggests that the polylines defining the polygonal\n"
34253 <<
"representation are not properly ordered.\n"
34254 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
34255 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34256 <<
"This should have failed when first trying to construct the\n"
34259 OOMPH_CURRENT_FUNCTION,
34260 OOMPH_EXCEPTION_LOCATION);
34266 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34286 unrefinement_tolerance);
34288 refinement_tolerance);
34295 this->copy_connection_information(polygon_pt->
polyline_pt(p),
34296 tmp_curve_section_pt);
34301 bool delete_it_on_destructor =
false;
34303 std::set<TriangleMeshCurveSection*>::iterator it =
34306 if (it!=this->Free_curve_section_pt.end())
34308 this->Free_curve_section_pt.erase(it);
34310 delete_it_on_destructor =
true;
34320 if (delete_it_on_destructor)
34331 for(
unsigned p=0;p<n_polyline;p++)
34333 face_mesh_pt[p]->flush_node_storage();
34334 delete face_mesh_pt[p];
34348 return (unrefinement_was_performed ||
34349 refinement_was_performed ||
34350 max_length_applied);
34364 template<
class ELEMENT>
34367 const bool& check_only)
34375 if (this->is_mesh_distributed() && !check_only)
34377 std::stringstream error_message;
34379 <<
"The updating of open curves of a distributed mesh can ONLY be\n"
34380 <<
"performed using the element's area associated to the halo(ed)\n"
34382 <<
"1) Make sure you have enabled the parallel mesh adaptation\n"
34383 <<
"option if you are working with a distributed mesh, OR\n"
34384 <<
"2) Make sure to call the update_..._using_elements_area() methods\n"
34385 <<
"if the mesh is marked as distributed\n\n";
34387 OOMPH_CURRENT_FUNCTION,
34388 OOMPH_EXCEPTION_LOCATION);
34394 bool unrefinement_was_performed=
false;
34395 bool refinement_was_performed=
false;
34396 bool max_length_applied =
false;
34405 get_face_mesh_representation(open_polyline_pt, face_mesh_pt);
34413 for(
unsigned p=0;p<n_polyline;p++)
34418 std::set<Vector<double> > vertex_nodes;
34421 const unsigned bound =
34425 const unsigned chunk =
34429 unsigned n_face_element = face_mesh_pt[p]->nelement();
34432 for(
unsigned e=0;
e<n_face_element;++
e)
34435 unsigned n_node = el_pt->
nnode();
34441 vertex_coord[0] = bound_left[0];
34444 for(
unsigned i=0;
i<2;
i++)
34446 vertex_coord[
i+1] = el_pt->
node_pt(0)->
x(
i);
34448 vertex_nodes.insert(vertex_coord);
34454 vertex_coord[0] = bound_right[0];
34457 for(
unsigned i=0;
i<2;
i++)
34459 vertex_coord[
i+1] = el_pt->
node_pt(n_node-1)->
x(
i);
34461 vertex_nodes.insert(vertex_coord);
34466 unsigned n_poly_vertex = vertex_nodes.size();
34469 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
34470 it!=vertex_nodes.end();++it)
34472 tmp_vector_vertex_node[count].resize(3);
34473 tmp_vector_vertex_node[count][0] = (*it)[0];
34474 tmp_vector_vertex_node[count][1] = (*it)[1];
34475 tmp_vector_vertex_node[count][2] = (*it)[2];
34480 unsigned n_vertex=tmp_vector_vertex_node.size();
34484 double unrefinement_tolerance=
34490 if (unrefinement_tolerance>0.0 && n_vertex>=3)
34492 unrefinement_was_performed =
34493 unrefine_boundary(bound, chunk, tmp_vector_vertex_node,
34494 unrefinement_tolerance, check_only);
34499 if (check_only && unrefinement_was_performed)
34503 for(
unsigned p=0;p<n_polyline;p++)
34505 face_mesh_pt[p]->flush_node_storage();
34506 delete face_mesh_pt[p];
34516 n_vertex=tmp_vector_vertex_node.size();
34521 double refinement_tolerance=
34523 if (refinement_tolerance>0.0 && n_vertex >= 2)
34525 refinement_was_performed =
34526 refine_boundary(face_mesh_pt[p], tmp_vector_vertex_node,
34527 refinement_tolerance, check_only);
34532 if (check_only && refinement_was_performed)
34536 for(
unsigned p=0;p<n_polyline;p++)
34538 face_mesh_pt[p]->flush_node_storage();
34539 delete face_mesh_pt[p];
34549 n_vertex=tmp_vector_vertex_node.size();
34555 if (maximum_length > 0.0 && n_vertex >= 2)
34557 bool max_length_applied =
false;
34558 max_length_applied =
34559 apply_max_length_constraint(face_mesh_pt[p],
34560 tmp_vector_vertex_node,
34565 if (check_only && max_length_applied)
34569 for(
unsigned p=0;p<n_polyline;p++)
34571 face_mesh_pt[p]->flush_node_storage();
34572 delete face_mesh_pt[p];
34581 n_vertex=tmp_vector_vertex_node.size();
34584 for(
unsigned i=0;
i<n_vertex;
i++)
34586 vector_vertex_node[
i].resize(2);
34587 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
34588 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
34591 #ifdef OOMPH_HAS_MPI
34595 if (!this->is_mesh_distributed())
34604 if( (p > 0) && !check_only )
34609 final_vertex_coordinate(final_vertex_of_previous_segment);
34611 unsigned prev_seg_boundary_id =
34616 double error = 0.0;
34617 for(
unsigned i=0;
i<2;
i++)
34619 const double dist =
34620 final_vertex_of_previous_segment[
i] -
34621 (*vector_vertex_node.begin())[
i];
34622 error += dist*dist;
34624 error = sqrt(error);
34633 for(
unsigned i=0;
i<2;
i++)
34635 const double dist =
34636 final_vertex_of_previous_segment[
i] -
34637 (*--vector_vertex_node.end())[
i];
34638 error += dist*dist;
34640 error = sqrt(error);
34655 initial_vertex_coordinate(initial_vertex_of_previous_segment);
34660 for(
unsigned i=0;
i<2;
i++)
34662 const double dist =
34663 initial_vertex_of_previous_segment[
i] -
34664 (*vector_vertex_node.begin())[
i];
34665 error += dist*dist;
34667 error = sqrt(error);
34676 for(
unsigned i=0;
i<2;
i++)
34678 const double dist =
34679 initial_vertex_of_previous_segment[
i] -
34680 (*--vector_vertex_node.end())[
i];
34681 error += dist*dist;
34683 error = sqrt(error);
34688 std::ostringstream error_stream;
34690 <<
"The distance between the first node of the current\n"
34691 <<
"line segment (boundary " << bound
34692 <<
") and either end of the previous line segment\n"
34693 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
34694 <<
"the desired tolerance " <<
34696 <<
"This suggests that the polylines defining the open "
34698 <<
"representation are not properly ordered.\n"
34699 <<
"Fail on last vertex of polyline: ("
34700 << prev_seg_boundary_id
34701 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
34702 <<
"This should have failed when first trying to construct\n"
34703 <<
"the open curve.\n";
34705 OOMPH_CURRENT_FUNCTION,
34706 OOMPH_EXCEPTION_LOCATION);
34713 std::reverse(vector_vertex_node.begin(),
34714 vector_vertex_node.end());
34725 std::ostringstream error_stream;
34727 <<
"The distance between the first node of the current\n"
34728 <<
"line segment (boundary " << bound <<
") and either end of "
34729 <<
"the previous line segment\n"
34730 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
34731 <<
"desired tolerance " <<
34733 <<
"This suggests that the polylines defining the polygonal\n"
34734 <<
"representation are not properly ordered.\n"
34735 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
34736 <<
") and\nfirst vertex of polyline ("<<bound<<
").\n"
34737 <<
"This should have failed when first trying to construct the\n"
34740 OOMPH_CURRENT_FUNCTION,
34741 OOMPH_EXCEPTION_LOCATION);
34747 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
34769 unrefinement_tolerance);
34771 refinement_tolerance);
34778 this->copy_connection_information(open_polyline_pt->
polyline_pt(p),
34779 tmp_curve_section);
34781 std::set<TriangleMeshCurveSection*>::iterator it =
34784 bool delete_it_on_destructor =
false;
34786 if (it!=this->Free_curve_section_pt.end())
34789 this->Free_curve_section_pt.erase(it);
34791 delete_it_on_destructor =
true;
34799 this->Boundary_curve_section_pt[bound] =
34802 if (delete_it_on_destructor)
34804 this->Free_curve_section_pt.insert(
34814 for(
unsigned p=0;p<n_polyline;p++)
34816 face_mesh_pt[p]->flush_node_storage();
34817 delete face_mesh_pt[p];
34831 return (unrefinement_was_performed ||
34832 refinement_was_performed ||
34833 max_length_applied);
34846 template<
class ELEMENT>
34851 double &unrefinement_tolerance,
34852 const bool &check_only)
34855 std::set<Vector<double> > no_delete_vertex;
34858 const bool boundary_receive_connections =
34859 this->boundary_connections(b, c, no_delete_vertex);
34863 bool unrefinement_was_performed=
false;
34865 unsigned n_vertex = vector_bnd_vertices.size();
34869 unsigned counter=1;
34875 for(
unsigned i=1;
i<=n_vertex-2;
i+=2)
34878 double a_x=vector_bnd_vertices[
i-1][1];
34879 double a_y=vector_bnd_vertices[
i-1][2];
34880 double b_x=vector_bnd_vertices[
i][1];
34881 double b_y=vector_bnd_vertices[
i][2];
34882 double c_x=vector_bnd_vertices[
i+1][1];
34883 double c_y=vector_bnd_vertices[
i+1][2];
34890 double e=
a*(a_x+b_x)+b*(a_y+b_y);
34891 double f=c*(a_x+c_x)+d*(a_y+c_y);
34893 double g=2.0*(
a*(c_y-b_y)-b*(c_x-b_x));
34896 if (std::fabs(g)<1.0e-14)
34899 if(check_only) {
return true;}
34903 double p_x=(d*
e-b*f)/g;
34904 double p_y=(
a*f-c*
e)/g;
34906 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
34908 double rhalfca_x=0.5*(a_x-c_x);
34909 double rhalfca_y=0.5*(a_y-c_y);
34911 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
34913 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
34918 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
34919 unrefinement_tolerance)
34922 if(check_only) {
return true;}
34928 if (do_it && boundary_receive_connections)
34931 for (std::set<
Vector<double> >::iterator it = no_delete_vertex.begin();
34932 it != no_delete_vertex.end(); it++)
34936 const double x = (*it)[0];
34937 const double y = (*it)[1];
34938 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
34939 error = sqrt(error);
34955 vector_bnd_vertices[
i].resize(0);
34974 if( (counter)==(n_vertex-1) )
34977 unsigned i=vector_bnd_vertices.size()-2;
34983 if(vector_bnd_vertices[counter-2].size()!=0)
35002 double a_x=vector_bnd_vertices[
n][1];
35003 double a_y=vector_bnd_vertices[
n][2];
35004 double b_x=vector_bnd_vertices[
i][1];
35005 double b_y=vector_bnd_vertices[
i][2];
35006 double c_x=vector_bnd_vertices[
i+1][1];
35007 double c_y=vector_bnd_vertices[
i+1][2];
35014 double e=
a*(a_x+b_x)+b*(a_y+b_y);
35015 double f=c*(a_x+c_x)+d*(a_y+c_y);
35017 double g=2.0*(
a*(c_y-b_y)-b*(c_x-b_x));
35020 if (std::fabs(g)<1.0e-14)
35023 if(check_only) {
return true;}
35027 double p_x=(d*
e-b*f)/g;
35028 double p_y=(
a*f-c*
e)/g;
35030 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
35032 double rhalfca_x=0.5*(a_x-c_x);
35033 double rhalfca_y=0.5*(a_y-c_y);
35035 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
35037 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
35042 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
35043 unrefinement_tolerance)
35046 if(check_only) {
return true;}
35052 if (do_it && boundary_receive_connections)
35055 for (std::set<
Vector<double> >::iterator it = no_delete_vertex.begin();
35056 it != no_delete_vertex.end(); it++)
35060 const double x = (*it)[0];
35061 const double y = (*it)[1];
35062 double error = (b_x - x)*(b_x - x) + (b_y - y)*(b_y - y);
35063 error = sqrt(error);
35080 vector_bnd_vertices[
i].resize(0);
35087 compact_vector.reserve(n_vertex);
35088 for (
unsigned i=0;
i<n_vertex;
i++)
35091 if (vector_bnd_vertices[
i].size()!=0)
35093 compact_vector.push_back(vector_bnd_vertices[
i]);
35098 n_vertex =compact_vector.size();
35104 if( n_vertex != vector_bnd_vertices.size() )
35106 unrefinement_was_performed=
true;
35110 vector_bnd_vertices.resize(n_vertex);
35111 for(
unsigned i=0;
i<n_vertex;
i++)
35113 vector_bnd_vertices[
i].resize(3);
35114 vector_bnd_vertices[
i][0]=compact_vector[
i][0];
35115 vector_bnd_vertices[
i][1]=compact_vector[
i][1];
35116 vector_bnd_vertices[
i][2]=compact_vector[
i][2];
35119 return unrefinement_was_performed;
35131 template<
class ELEMENT>
35135 double &refinement_tolerance,
35136 const bool &check_only)
35140 bool refinement_was_performed=
false;
35147 unsigned n_vertex=vector_bnd_vertices.size();
35155 extended_vector.reserve(2*n_vertex);
35158 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35161 double zeta_left=vector_bnd_vertices[inod][0];
35165 for(
unsigned i=0;
i<2;
i++)
35167 R_left[
i]=vector_bnd_vertices[inod][
i+1];
35171 double zeta_right=vector_bnd_vertices[inod+1][0];
35175 for(
unsigned i=0;
i<2;
i++)
35177 R_right[
i]=vector_bnd_vertices[inod+1][
i+1];
35182 zeta_mid[0]=0.5*(zeta_left+zeta_right);
35187 mesh_geom_obj_pt->
position(zeta_mid,R_mid);
35192 for(
unsigned i=0;
i<2;
i++)
35194 R_mid_polygon[
i]=0.5*(R_right[
i]+R_left[
i]);
35199 double distance=sqrt((R_mid[0]-R_mid_polygon[0])*
35200 (R_mid[0]-R_mid_polygon[0])+
35201 (R_mid[1]-R_mid_polygon[1])*
35202 (R_mid[1]-R_mid_polygon[1]));
35205 double length=sqrt((R_right[0]-R_left[0])*(R_right[0]-R_left[0])+
35206 (R_right[1]-R_left[1])*(R_right[1]-R_left[1]));
35212 if((distance/length) > refinement_tolerance)
35219 delete mesh_geom_obj_pt;
35224 new_node[0]=zeta_mid[0];
35225 new_node[1]=R_mid[0];
35226 new_node[2]=R_mid[1];
35229 extended_vector.push_back(vector_bnd_vertices[inod]);
35232 extended_vector.push_back(new_node);
35239 extended_vector.push_back(vector_bnd_vertices[inod]);
35244 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35247 n_vertex=extended_vector.size();
35252 if( n_vertex != vector_bnd_vertices.size() )
35254 refinement_was_performed=
true;
35258 vector_bnd_vertices.resize(n_vertex);
35259 for(
unsigned i=0;
i<n_vertex;
i++)
35261 vector_bnd_vertices[
i].resize(3);
35262 vector_bnd_vertices[
i][0]=extended_vector[
i][0];
35263 vector_bnd_vertices[
i][1]=extended_vector[
i][1];
35264 vector_bnd_vertices[
i][2]=extended_vector[
i][2];
35269 delete mesh_geom_obj_pt;
35271 return refinement_was_performed;
35281 template<
class ELEMENT>
35285 double &max_length_constraint)
35289 bool max_length_applied=
false;
35296 unsigned n_vertex=vector_bnd_vertices.size();
35303 for(
unsigned inod=0;inod<n_vertex-1;inod++)
35306 double zeta_left=vector_bnd_vertices[inod][0];
35310 for(
unsigned i=0;
i<2;
i++)
35312 R_left[
i]=vector_bnd_vertices[inod][
i+1];
35316 double zeta_right=vector_bnd_vertices[inod+1][0];
35320 for(
unsigned i=0;
i<2;
i++)
35322 R_right[
i]=vector_bnd_vertices[inod+1][
i+1];
35326 extended_vector.push_back(vector_bnd_vertices[inod]);
35330 double length=std::fabs(zeta_right-zeta_left);
35333 if (length > max_length_constraint)
35335 double n_pts = length/max_length_constraint;
35337 unsigned n_points =
static_cast<unsigned>(n_pts);
35338 double zeta_increment = (zeta_right-zeta_left)/((
double)n_points+1);
35342 for(
unsigned s=1;
s<n_points+1;
s++)
35345 zeta[0]= zeta_left + zeta_increment*double(
s);
35347 mesh_geom_obj_pt->
position(zeta, vertex);
35351 new_node[0]=zeta[0];
35352 new_node[1]=vertex[0];
35353 new_node[2]=vertex[1];
35356 extended_vector.push_back(new_node);
35362 extended_vector.push_back(vector_bnd_vertices[n_vertex-1]);
35365 n_vertex=extended_vector.size();
35370 if( n_vertex != vector_bnd_vertices.size() )
35372 max_length_applied =
true;
35376 vector_bnd_vertices.resize(n_vertex);
35377 for(
unsigned i=0;
i<n_vertex;
i++)
35379 vector_bnd_vertices[
i].resize(3);
35380 vector_bnd_vertices[
i][0]=extended_vector[
i][0];
35381 vector_bnd_vertices[
i][1]=extended_vector[
i][1];
35382 vector_bnd_vertices[
i][2]=extended_vector[
i][2];
35387 delete mesh_geom_obj_pt;
35389 return max_length_applied;
35399 template<
class ELEMENT>
35402 const unsigned &boundary_id,
35403 Mesh* face_mesh_pt)
35410 this->
template build_face_mesh<ELEMENT,FaceElementAsGeomObject>
35411 (boundary_id,face_mesh_pt);
35414 unsigned n_element = face_mesh_pt->
nelement();
35416 for(
unsigned e=0;
e<n_element;
e++)
35436 template<
class ELEMENT>
35439 const unsigned &boundary_id,
35440 Mesh* face_mesh_pt,
35441 std::map<FiniteElement*, bool> &is_inverted,
35442 bool &inverted_face_mesh)
35444 Mesh *tmp_unsorted_face_mesh_pt =
new Mesh();
35447 create_unsorted_face_mesh_representation(
35448 boundary_id, tmp_unsorted_face_mesh_pt);
35458 std::list<FiniteElement*> sorted_el_pt;
35460 sorted_el_pt.push_back(el_pt);
35463 unsigned nnod=el_pt->
nnode();
35466 unsigned count_done=0;
35469 unsigned n_face_element = tmp_unsorted_face_mesh_pt->
nelement();
35472 std::map<FiniteElement*,bool> done_el;
35474 is_inverted.clear();
35477 for (
unsigned ee=1;ee<n_face_element;ee++)
35481 for (
unsigned e=1;
e<n_face_element;
e++)
35487 if (!done_el[el_pt])
35491 std::list<FiniteElement*>::iterator it=sorted_el_pt.end();
35497 if (is_inverted[first_el_pt])
35499 left_node_pt=first_el_pt->node_pt(nnod-1);
35502 if (is_inverted[last_el_pt])
35504 right_node_pt=last_el_pt->node_pt(0);
35508 if (left_node_pt==el_pt->node_pt(nnod-1))
35510 sorted_el_pt.push_front(el_pt);
35511 done_el[el_pt]=
true;
35513 is_inverted[el_pt]=
false;
35517 else if (left_node_pt==el_pt->node_pt(0))
35519 sorted_el_pt.push_front(el_pt);
35520 done_el[el_pt]=
true;
35522 is_inverted[el_pt]=
true;
35526 else if(right_node_pt==el_pt->node_pt(0))
35528 sorted_el_pt.push_back(el_pt);
35529 done_el[el_pt]=
true;
35531 is_inverted[el_pt]=
false;
35535 else if (right_node_pt==el_pt->node_pt(nnod-1))
35537 sorted_el_pt.push_back(el_pt);
35538 done_el[el_pt]=
true;
35540 is_inverted[el_pt]=
true;
35543 if (done_el[el_pt])
35552 if (count_done!=(n_face_element-1))
35554 std::ostringstream error_message;
35556 <<
"When ordering FaceElements on "
35557 <<
"boundary " << boundary_id <<
" only managed to order \n" << count_done
35558 <<
" of " << n_face_element <<
" face elements.\n"
35561 error_message.str(),
35562 OOMPH_CURRENT_FUNCTION,
35563 OOMPH_EXCEPTION_LOCATION);
35570 for (std::list<FiniteElement*>::iterator it=sorted_el_pt.begin();
35571 it!=sorted_el_pt.end();it++)
35588 this->Boundary_curve_section_pt[boundary_id];
35600 unsigned n_node = first_el_pt->
nnode();
35604 if (is_inverted[first_el_pt])
35606 first_node_pt = first_el_pt->node_pt(n_node-1);
35609 double error = (first_node_pt->
x(0) - first_vertex[0])*
35610 (first_node_pt->
x(0) - first_vertex[0]) +
35611 (first_node_pt->
x(1) - first_vertex[1])*
35612 (first_node_pt->
x(1) - first_vertex[1]);
35614 error = sqrt(error);
35619 inverted_face_mesh =
false;
35623 inverted_face_mesh =
true;
35633 template<
class ELEMENT>
35639 unsigned n_polyline = polygon_pt->
npolyline();
35640 face_mesh_pt.resize(n_polyline);
35646 bool eligible_for_segment_redistribution=
true;
35649 for(
unsigned p=0;p<n_polyline;p++)
35659 this->boundary_geom_object_pt(bound);
35660 if(geom_object_pt!=0)
35662 eligible_for_segment_redistribution=
false;
35665 face_mesh_pt[p] =
new Mesh();
35666 create_unsorted_face_mesh_representation(
35667 bound, face_mesh_pt[p]);
35677 if(this->nregion() > 1)
35679 std::ostringstream warn_message;
35681 <<
"Can't currently re-distribute segments between polylines if there\n"
35682 <<
"are multiple regions; returning..." << std::endl;
35684 "RefineableTriangleMesh::get_face_mesh_representation()",
35685 OOMPH_EXCEPTION_LOCATION);
35690 if (!eligible_for_segment_redistribution)
35692 std::ostringstream warn_message;
35694 <<
"Over-ruling re-distribution of segments between polylines\n"
35695 <<
"because at least one boundary is associated with a GeomObject."
35696 <<
"Returning..." << std::endl;
35698 "RefineableTriangleMesh::get_face_mesh_representation()",
35699 OOMPH_EXCEPTION_LOCATION);
35707 double s_total=0.0;
35713 std::vector<bool> is_reversed(n_polyline,
false);
35716 for(
unsigned p=0;p<n_polyline;p++)
35723 std::list<FiniteElement*> ordered_el_pt;
35724 FiniteElement* el_pt=face_mesh_pt[p]->finite_element_pt(0);
35725 ordered_el_pt.push_back(el_pt);
35728 unsigned nnod=el_pt->
nnode();
35731 first_polyline_node_pt[p]=el_pt->
node_pt(0);
35732 last_polyline_node_pt[p]=el_pt->
node_pt(nnod-1);
35735 unsigned count_done=0;
35738 unsigned n_face_element = face_mesh_pt[p]->nelement();
35745 std::map<FiniteElement*,bool> done_el;
35748 std::map<FiniteElement*,bool> is_inverted;
35751 for (
unsigned ee=1;ee<n_face_element;ee++)
35755 for (
unsigned e=1;
e<n_face_element;
e++)
35758 el_pt=face_mesh_pt[p]->finite_element_pt(
e);
35761 if (!done_el[el_pt])
35765 std::list<FiniteElement*>::iterator it=ordered_el_pt.end();
35771 if (is_inverted[first_el_pt])
35773 left_node_pt=first_el_pt->node_pt(nnod-1);
35776 if (is_inverted[last_el_pt])
35778 right_node_pt=last_el_pt->node_pt(0);
35782 if (left_node_pt==el_pt->node_pt(nnod-1))
35784 ordered_el_pt.push_front(el_pt);
35785 done_el[el_pt]=
true;
35787 is_inverted[el_pt]=
false;
35788 first_polyline_node_pt[p]=el_pt->node_pt(0);
35792 else if (left_node_pt==el_pt->node_pt(0))
35794 ordered_el_pt.push_front(el_pt);
35795 done_el[el_pt]=
true;
35797 is_inverted[el_pt]=
true;
35798 first_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35802 else if(right_node_pt==el_pt->node_pt(0))
35804 ordered_el_pt.push_back(el_pt);
35805 done_el[el_pt]=
true;
35807 is_inverted[el_pt]=
false;
35808 last_polyline_node_pt[p]=el_pt->node_pt(nnod-1);
35812 else if (right_node_pt==el_pt->node_pt(nnod-1))
35814 ordered_el_pt.push_back(el_pt);
35815 done_el[el_pt]=
true;
35817 is_inverted[el_pt]=
true;
35818 last_polyline_node_pt[p]=el_pt->node_pt(0);
35821 if (done_el[el_pt])
35830 if (count_done!=(n_face_element-1))
35832 std::ostringstream error_message;
35834 <<
"When ordering FaceElements on "
35835 <<
"boundary " << bound <<
" only managed to order \n" << count_done
35836 <<
" of " << n_face_element <<
" face elements.\n"
35839 error_message.str(),
35840 OOMPH_CURRENT_FUNCTION,
35841 OOMPH_EXCEPTION_LOCATION);
35845 ordered_face_mesh_pt[p] =
new Mesh;
35848 for (std::list<FiniteElement*>::iterator it=ordered_el_pt.begin();
35849 it!=ordered_el_pt.end();it++)
35855 ordered_face_mesh_pt[p]->add_element_pt(el_pt);
35859 for(
unsigned e=0;
e<n_face_element;++
e)
35861 FiniteElement* el_pt=ordered_face_mesh_pt[p]->finite_element_pt(
e);
35862 unsigned n_node=el_pt->
nnode();
35863 double element_length_squared=0.0;
35864 for(
unsigned i=0;
i<2;
i++)
35866 element_length_squared += pow(el_pt->
node_pt(n_node-1)->
x(
i)-
35871 double element_length=sqrt(element_length_squared);
35874 s_total += element_length;
35878 face_mesh_pt[p]->flush_element_and_node_storage();
35882 if ((last_polyline_node_pt[0]==first_polyline_node_pt[1])||
35883 (last_polyline_node_pt[0]==last_polyline_node_pt[1]))
35885 is_reversed[0]=
false;
35887 else if ((first_polyline_node_pt[0]==first_polyline_node_pt[1])||
35888 (first_polyline_node_pt[0]==last_polyline_node_pt[1]))
35890 is_reversed[0]=
true;
35895 std::vector<bool> mesh_done(n_polyline,
false);
35899 tmp_face_mesh_pt[0]=ordered_face_mesh_pt[0];
35900 unsigned current=0;
35901 old_polyline_number[0]=0;
35902 unsigned count_found=0;
35905 for(
unsigned p=1;p<n_polyline;p++)
35907 Node* end_node_pt=last_polyline_node_pt[current];
35908 if (is_reversed[current])
35910 end_node_pt=first_polyline_node_pt[current];
35914 for(
unsigned pp=1;pp<n_polyline;pp++)
35916 if (!mesh_done[pp])
35919 if ((!is_reversed[current])&&
35920 (end_node_pt==first_polyline_node_pt[pp]))
35922 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35923 mesh_done[pp]=
true;
35924 is_reversed[pp]=
false;
35925 old_polyline_number[p]=pp;
35932 else if ((!is_reversed[current])&&
35933 (end_node_pt==last_polyline_node_pt[pp]))
35935 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35936 mesh_done[pp]=
true;
35937 is_reversed[pp]=
true;
35938 old_polyline_number[p]=pp;
35945 else if ((is_reversed[current])&&
35946 (end_node_pt==first_polyline_node_pt[pp]))
35948 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35949 mesh_done[pp]=
true;
35950 is_reversed[pp]=
false;
35951 old_polyline_number[p]=pp;
35958 else if ((is_reversed[current])&&
35959 (end_node_pt==last_polyline_node_pt[pp]))
35961 tmp_face_mesh_pt[p]=ordered_face_mesh_pt[pp];
35962 mesh_done[pp]=
true;
35963 is_reversed[pp]=
true;
35964 old_polyline_number[p]=pp;
35974 if (count_found!=n_polyline-1)
35976 std::ostringstream error_message;
35977 error_message <<
"Only found " << count_found
35978 <<
" out of " << n_polyline-1
35979 <<
" polylines to be fitted in.\n";
35981 error_message.str(),
35982 OOMPH_CURRENT_FUNCTION,
35983 OOMPH_EXCEPTION_LOCATION);
35988 for (
unsigned i=0;
i<n_polyline;
i++)
35990 ordered_face_mesh_pt[
i]=tmp_face_mesh_pt[
i];
35996 unsigned new_face_id=0;
36000 std::map<Node*,std::map<unsigned,unsigned> >
36001 node_must_not_be_removed_from_boundary_flag;
36004 for(
unsigned p=0;p<n_polyline;p++)
36007 unsigned n_face_element = ordered_face_mesh_pt[p]->nelement();
36008 for (
unsigned e=0;
e<n_face_element;
e++)
36010 unsigned el_number=
e;
36011 if (is_reversed[p])
36013 el_number=n_face_element-
e-1;
36017 ordered_face_mesh_pt[p]->finite_element_pt(el_number);
36018 unsigned n_node = el_pt->
nnode();
36021 double element_length_squared=0.0;
36022 for(
unsigned i=0;
i<2;
i++)
36024 element_length_squared += pow(el_pt->
node_pt(n_node-1)->
x(
i)-
36027 double element_length=sqrt(element_length_squared);
36030 s += element_length;
36034 if(
s < s_total/
double(n_polyline)+1
e-6)
36037 face_mesh_pt[new_face_id]->add_element_pt(el_pt);
36039 unsigned bound_old =
36042 unsigned bound_new =
36046 for(
unsigned i=0;
i<n_node;
i++)
36053 if(bound_new != bound_old)
36056 add_boundary_node(bound_new,nod_pt);
36060 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=0;
36069 node_must_not_be_removed_from_boundary_flag[nod_pt][bound_old]+=1;
36081 if(new_face_id!=n_polyline-1)
36099 unsigned move_count=0;
36100 for (std::map<
Node*,std::map<unsigned,unsigned> >::iterator
36101 it=node_must_not_be_removed_from_boundary_flag.begin();
36102 it!=node_must_not_be_removed_from_boundary_flag.end();it++)
36105 Node* nod_pt=(*it).first;
36108 for (std::map<unsigned,unsigned>::iterator
36109 it_2=(*it).second.begin();it_2!=(*it).second.end();it_2++)
36112 unsigned bound=(*it_2).first;
36115 if((*it_2).second==0)
36117 remove_boundary_node(bound,nod_pt);
36124 for(
unsigned p=0;p<n_polyline;p++)
36131 unsigned n_face_element = face_mesh_pt[p]->nelement();
36132 for(
unsigned e=0;
e<n_face_element;
e++)
36137 (face_mesh_pt[p]->element_pt(
e));
36145 setup_boundary_element_info();
36148 for(
unsigned p=0;p<n_polyline;p++)
36155 this->
template setup_boundary_coordinates<ELEMENT>(bound);
36159 for(
unsigned p=0;p<n_polyline;p++)
36164 ordered_face_mesh_pt[p]->flush_element_and_node_storage();
36165 delete ordered_face_mesh_pt[p];
36173 template<
class ELEMENT>
36181 face_mesh_pt.resize(n_polyline);
36184 for(
unsigned p=0;p<n_polyline;p++)
36191 face_mesh_pt[p] =
new Mesh();
36192 create_unsorted_face_mesh_representation(
36193 bound, face_mesh_pt[p]);
36206 template <
class ELEMENT>
36209 &internal_point_coord,
36210 const bool& check_only)
36214 bool update_was_performed=
false;
36216 unsigned n_hole = internal_point_coord.size();
36217 for(
unsigned ihole=0;ihole<n_hole;ihole++)
36221 = this->Internal_polygon_pt[ihole];
36231 internal_point_coord[ihole].resize(2);
36245 bool update_necessary=
36246 this->update_polygon_using_face_mesh(poly_pt,check_only);
36249 if(update_necessary)
36259 update_was_performed=
36260 this->update_polygon_using_face_mesh(poly_pt);
36278 if(this->Internal_hole_point_update_fct_pt!=0)
36280 this->Internal_hole_point_update_fct_pt(ihole,poly_pt);
36287 unsigned n_polyline = poly_pt->
npolyline();
36290 vertex_coord.resize(2);
36291 internal_point_coord[ihole].resize(2);
36295 internal_point_coord[ihole][0] = 0.0;
36296 internal_point_coord[ihole][1] = 0.0;
36298 for(
unsigned p=0;p<n_polyline;p++)
36303 for(
unsigned v=0;v<n_vertex;v++)
36306 for(
unsigned i=0;
i<2;
i++)
36308 poly_ave[
i] += vertex_coord[
i];
36313 for(
unsigned i=0;
i<2;
i++)
36315 internal_point_coord[ihole][
i] += poly_ave[
i]/n_vertex;
36320 for(
unsigned i=0;
i<2;
i++)
36322 internal_point_coord[ihole][
i] /= n_polyline;
36386 return update_was_performed;
36395 template<
class ELEMENT>
36404 std::ifstream node_file(node_file_name.c_str(),std::ios_base::in);
36407 if(!node_file.is_open())
36409 std::string error_msg(
"Failed to open node file: ");
36410 error_msg +=
"\"" + node_file_name +
"\".";
36412 OOMPH_EXCEPTION_LOCATION);
36417 node_file >> nnodes;
36420 unsigned dimension;
36421 node_file >> dimension;
36427 OOMPH_CURRENT_FUNCTION,
36428 OOMPH_EXCEPTION_LOCATION);
36437 unsigned npoint_attributes;
36438 node_file >> npoint_attributes;;
36441 unsigned boundary_markers_flag=0;
36442 node_file >> boundary_markers_flag;
36445 unsigned dummy_node_number;
36447 unsigned dummy_node_attribute;
36449 unsigned dummy_node_boundary;
36453 for(
unsigned i=0;
i<nnodes;
i++)
36455 node_file>>dummy_node_number;
36456 node_file>>x_node[
i];
36457 node_file>>y_node[
i];
36458 for(
unsigned j=0;j<npoint_attributes;++j)
36460 node_file>>dummy_node_attribute;
36462 if(boundary_markers_flag)
36464 node_file>>dummy_node_boundary;
36473 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >
36474 unsorted_boundary_segments;
36485 std::ifstream poly_file(poly_file_name.c_str(),std::ios_base::in);
36488 if(!poly_file.is_open())
36490 std::string error_msg(
"Failed to open poly file: ");
36491 error_msg +=
"\"" + poly_file_name +
"\".";
36493 OOMPH_EXCEPTION_LOCATION);
36497 unsigned n_node_poly;
36498 poly_file >> n_node_poly;
36501 poly_file >> dimension;
36504 unsigned attribute_flag;
36505 poly_file >> attribute_flag;
36508 poly_file >> boundary_markers_flag;
36513 for(
unsigned i=0;
i<n_node_poly;
i++)
36520 for(
unsigned j=0;j<attribute_flag;++j)
36522 poly_file >> dummy;
36525 if(boundary_markers_flag==1)
36532 unsigned read_value;
36535 poly_file >> read_value;
36536 const unsigned nglobal_segments = read_value;
36539 poly_file >> boundary_markers_flag;
36542 unsigned global_segment_number;
36545 std::set<unsigned> nodes_ids;
36548 for(
unsigned i=0;
i<nglobal_segments;
i++)
36551 unsigned lnode_id=0;
36552 unsigned rnode_id=0;
36554 poly_file >> global_segment_number;
36555 poly_file >> lnode_id;
36556 poly_file >> rnode_id;
36557 nodes_ids.insert(lnode_id);
36558 nodes_ids.insert(rnode_id);
36559 if(boundary_markers_flag)
36561 poly_file >> bnd_id;
36567 unsorted_boundary_segments[bnd_id-1].push_back(
36568 std::make_pair(lnode_id, rnode_id));
36575 const unsigned nsorted_boundaries_ids =
36576 sorted_boundaries_ids.size();
36578 bool boundary_id_found =
false;
36579 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36581 if (sorted_boundaries_ids[ib] == bnd_id - 1)
36583 boundary_id_found =
true;
36589 if (!boundary_id_found)
36591 sorted_boundaries_ids.push_back(bnd_id - 1);
36601 if (nglobal_segments != nodes_ids.size())
36603 std::ostringstream error_message;
36605 <<
"The number of nodes (" << nodes_ids.size() <<
") and segments ("
36606 << nglobal_segments <<
") is different.\nThis may mean that there "
36607 <<
"are internal non-closed boundaries defined in\nthe polyfile. "
36608 <<
"If you need this feature please use the TriangleMeshPoyLine\n"
36609 <<
"and TriangleMeshCurviLine objects to define your domain.\n\n";
36611 OOMPH_CURRENT_FUNCTION,
36612 OOMPH_EXCEPTION_LOCATION);
36619 const unsigned nboundary = unsorted_boundary_segments.size();
36622 if (nboundary != this->nboundary())
36624 std::ostringstream error_message;
36626 <<
"The number of boundaries on the mesh (" << this->nboundary()
36627 <<
") is different from the number of\nboundaries read from the "
36628 <<
"polyfiles (" << unsorted_boundary_segments.size() <<
")!!!\n\n\n";
36630 OOMPH_CURRENT_FUNCTION,
36631 OOMPH_EXCEPTION_LOCATION);
36637 const unsigned nsorted_boundaries_ids =
36638 sorted_boundaries_ids.size();
36640 if (nsorted_boundaries_ids != this->nboundary())
36642 std::ostringstream error_message;
36644 <<
"The number of boundaries on the mesh (" << this->nboundary()
36645 <<
") is different from the number of\nsorted boundaries ids read "
36646 <<
"from the polyfiles (" << nsorted_boundaries_ids <<
")!!!\n\n\n";
36648 OOMPH_CURRENT_FUNCTION,
36649 OOMPH_EXCEPTION_LOCATION);
36654 std::map<unsigned, std::list<unsigned> > sorted_boundary_segments;
36657 std::map<unsigned,Vector<std::pair<unsigned,unsigned> > >::iterator it;
36659 for (it = unsorted_boundary_segments.begin();
36660 it != unsorted_boundary_segments.end();
36665 const unsigned bnd_id = (*it).first;
36669 std::map<std::pair<unsigned, unsigned>,
bool> segment_done;
36670 const unsigned nsegments = segments_edges.size();
36673 std::list<unsigned> sorted_segments;
36676 unsigned left_node_id = segments_edges[0].first;
36677 unsigned right_node_id = segments_edges[0].second;
36680 sorted_segments.push_back(left_node_id);
36681 sorted_segments.push_back(right_node_id);
36684 segment_done[segments_edges[0]] =
true;
36687 unsigned nsorted_segments = 1;
36689 while(nsorted_segments < nsegments)
36691 for (
unsigned i = 1;
i < nsegments;
i++)
36694 if (!segment_done[segments_edges[
i]])
36697 unsigned current_left_node_id = segments_edges[
i].first;
36698 unsigned current_right_node_id = segments_edges[
i].second;
36702 if (current_left_node_id == right_node_id)
36706 sorted_segments.push_back(current_right_node_id);
36708 nsorted_segments++;
36710 segment_done[segments_edges[
i]] =
true;
36712 right_node_id = current_right_node_id;
36716 else if (current_right_node_id == left_node_id)
36720 sorted_segments.push_front(current_left_node_id);
36722 nsorted_segments++;
36724 segment_done[segments_edges[
i]] =
true;
36726 left_node_id = current_left_node_id;
36730 else if (current_left_node_id == left_node_id)
36734 sorted_segments.push_front(current_right_node_id);
36736 nsorted_segments++;
36738 segment_done[segments_edges[
i]] =
true;
36740 left_node_id = current_right_node_id;
36744 else if (current_right_node_id == right_node_id)
36748 sorted_segments.push_back(current_left_node_id);
36750 nsorted_segments++;
36752 segment_done[segments_edges[
i]] =
true;
36754 right_node_id = current_left_node_id;
36762 sorted_boundary_segments[bnd_id] = sorted_segments;
36768 if (sorted_boundary_segments.size() != this->nboundary())
36770 std::ostringstream error_message;
36772 <<
"The number of boundaries on the mesh (" << this->nboundary()
36773 <<
") is different from the number\nof sorted boundaries to create the "
36774 <<
"polylines (" << sorted_boundary_segments.size() <<
")\n\n";
36776 OOMPH_CURRENT_FUNCTION,
36777 OOMPH_EXCEPTION_LOCATION);
36784 unsigned current_polyline = 0;
36787 for (
unsigned ib = 0; ib < nsorted_boundaries_ids; ib++)
36790 const unsigned bnd_id = sorted_boundaries_ids[ib];
36795 for (std::list<unsigned>::iterator it_list =
36796 sorted_boundary_segments[bnd_id].begin();
36797 it_list != sorted_boundary_segments[bnd_id].end();
36799 {nodes_ids.push_back((*it_list));}
36802 const unsigned nvertices = nodes_ids.size();
36808 for (
unsigned i = 0;
i < nvertices;
i++)
36811 vertices[
i].resize(2);
36812 vertices[
i][0] = x_node[nodes_ids[
i]-1];
36813 vertices[
i][1] = y_node[nodes_ids[
i]-1];
36821 polylines_pt[current_polyline] =
36825 this->Boundary_curve_section_pt[bnd_id] =
36829 current_polyline++;
36836 unsigned nsorted_polylines = 0;
36839 unsigned npolygons = 0;
36845 std::map<unsigned, bool> polyline_done;
36846 while(nsorted_polylines < nboundary)
36849 std::list<TriangleMeshCurveSection*> sorted_curve_sections_pt;
36851 unsigned init_poly = 0;
36853 bool found_root_polyline =
false;
36856 for (
unsigned i = 0;
i < nboundary;
i++)
36858 if (!polyline_done[
i])
36862 nsorted_polylines++;
36865 found_root_polyline =
true;
36868 polyline_done[
i] =
true;
36870 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
36877 if (!found_root_polyline)
36879 std::ostringstream error_message;
36881 <<
"Was not possible to found the root polyline to create polygons\n\n";
36883 OOMPH_CURRENT_FUNCTION,
36884 OOMPH_EXCEPTION_LOCATION);
36889 const unsigned bnd_id = polylines_pt[init_poly]->boundary_id();
36891 unsigned left_node_id = sorted_boundary_segments[bnd_id].front();
36892 unsigned right_node_id = sorted_boundary_segments[bnd_id].back();
36895 bool closed_polygon =
false;
36900 for (
unsigned i = init_poly;
i < nboundary;
i++)
36903 if (!polyline_done[
i])
36908 const unsigned cbnd_id = polylines_pt[
i]->boundary_id();
36910 unsigned cleft_node_id = sorted_boundary_segments[cbnd_id].front();
36911 unsigned cright_node_id = sorted_boundary_segments[cbnd_id].back();
36915 if (cleft_node_id == right_node_id)
36918 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
36920 polyline_done[
i] =
true;
36922 right_node_id = cright_node_id;
36924 nsorted_polylines++;
36928 else if (cright_node_id == left_node_id)
36931 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
36933 polyline_done[
i] =
true;
36935 left_node_id = cleft_node_id;
36937 nsorted_polylines++;
36941 else if (cleft_node_id == left_node_id)
36944 polylines_pt[
i]->reverse();
36946 sorted_curve_sections_pt.push_front(polylines_pt[
i]);
36948 polyline_done[
i] =
true;
36950 left_node_id = cright_node_id;
36952 nsorted_polylines++;
36956 else if (cright_node_id == right_node_id)
36959 polylines_pt[
i]->reverse();
36961 sorted_curve_sections_pt.push_back(polylines_pt[
i]);
36963 polyline_done[
i] =
true;
36965 right_node_id = cleft_node_id;
36967 nsorted_polylines++;
36976 if (left_node_id == right_node_id)
36979 closed_polygon =
true;
36982 }
while(nsorted_polylines < nboundary && !closed_polygon);
36985 if (!closed_polygon)
36987 std::ostringstream error_message;
36989 <<
"It was not possible to create a closed curve, these are the "
36990 <<
"vertices of the already sorted polylines\n\n";
36991 unsigned cpolyline = 0;
36992 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
36993 sorted_curve_sections_pt.begin();
36994 it_list != sorted_curve_sections_pt.end();
36997 error_message <<
"Polyline (" << cpolyline <<
")\n";
37000 const unsigned nvertex = tmp_poly_pt->
nvertex();
37001 for (
unsigned v = 0; v < nvertex; v++)
37006 error_message <<
"\n";
37010 OOMPH_CURRENT_FUNCTION,
37011 OOMPH_EXCEPTION_LOCATION);
37018 for (std::list<TriangleMeshCurveSection*>::iterator it_list =
37019 sorted_curve_sections_pt.begin();
37020 it_list != sorted_curve_sections_pt.end();
37022 {tmp_sorted_curve_sections_pt.push_back((*it_list));}
37029 this->Free_polygon_pt.insert(polygon_pt);
37032 polygons_pt.push_back(polygon_pt);
37045 unsigned index_outer = 0;
37047 for (
unsigned idx_outer = 0; idx_outer < npolygons; idx_outer++)
37054 bool all_inner_inside =
true;
37057 const unsigned nouter_polylines = polygons_pt[idx_outer]->npolyline();
37058 for (
unsigned p = 0; p < nouter_polylines; p++)
37061 polygons_pt[idx_outer]->polyline_pt(p);
37062 const unsigned nvertex = tmp_poly_pt->
nvertex();
37063 for (
unsigned v = 0; v < nvertex; v++)
37066 outer_vertex_coordinates.push_back(current_vertex);
37075 const unsigned ninner_polygons = polygons_pt.size() - 1;
37080 for (
unsigned i = 0;
i <= ninner_polygons;
i++)
37082 if (
i != idx_outer)
37085 const unsigned ninner_polylines = polygons_pt[
i]->npolyline();
37086 for (
unsigned p = 0; p < ninner_polylines; p++)
37089 const unsigned nvertex = tmp_poly_pt->
nvertex();
37090 for (
unsigned v = 0; v < nvertex; v++)
37095 inner_vertex_coordinates[
i].push_back(current_vertex);
37097 else if (
i > idx_outer)
37099 inner_vertex_coordinates[
i-1].push_back(current_vertex);
37111 for (
unsigned i = 0;
i < ninner_polygons;
i++)
37115 const unsigned nvertex_internal = inner_vertex_coordinates[
i].size();
37116 for (
unsigned v = 0; v < nvertex_internal; v++)
37120 all_inner_inside &=
37121 this->is_point_inside_polygon_helper(outer_vertex_coordinates,
37126 if (!all_inner_inside)
37136 if (!all_inner_inside)
37146 if (all_inner_inside)
37148 index_outer = idx_outer;
37158 if (index_outer != 0)
37160 std::ostringstream warning_message;
37162 <<
"The first set of nodes listed in the input polyfiles does not\n"
37163 <<
"correspond to the outer closed boundary. This may lead to\n"
37164 <<
"problems at the adaptation stage if the holes coordinates\n"
37165 <<
"are no correctly associated to the inner closed boundaries.\n"
37166 <<
"You can check the generated mesh by calling the output() method\n"
37167 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37169 OOMPH_CURRENT_FUNCTION,
37170 OOMPH_EXCEPTION_LOCATION);
37179 this->Outer_boundary_pt.resize(1);
37180 this->Outer_boundary_pt[0] = polygons_pt[index_outer];
37182 this->Internal_polygon_pt.resize(npolygons-1);
37183 for (
unsigned i = 0;
i < npolygons;
i++)
37185 if (
i != index_outer)
37187 if (
i < index_outer)
37190 this->Internal_polygon_pt[
i] = polygons_pt[
i];
37192 else if (
i > index_outer)
37195 this->Internal_polygon_pt[
i-1] = polygons_pt[
i];
37208 for (
unsigned i = 0;
i < npolygons-1;
i++)
37211 const unsigned ninner_polylines =
37212 this->Internal_polygon_pt[
i]->npolyline();
37213 for (
unsigned p = 0; p < ninner_polylines; p++)
37216 this->Internal_polygon_pt[
i]->polyline_pt(p);
37219 const unsigned nvertex = tmp_poly_pt->
nvertex();
37220 for (
unsigned v = 0; v < nvertex; v++)
37223 inner_vertex_coordinates[
i].push_back(current_vertex);
37232 poly_file >> nholes;
37235 if (npolygons > 1 && (npolygons - 1) != nholes)
37237 std::ostringstream error_message;
37239 <<
"The number of holes (" << nholes <<
") does not correspond "
37240 <<
"with the number\nof internal polygons ("
37241 << npolygons - 1 <<
")\n\n"
37242 <<
"Using polyfiles as input does not currently allows the\n"
37243 <<
"definition of more than one outer polygon\n\n";
37245 OOMPH_CURRENT_FUNCTION,
37246 OOMPH_EXCEPTION_LOCATION);
37254 unsigned dummy_hole;
37256 for(
unsigned ihole=0;ihole<nholes;ihole++)
37258 hole_coordinates[ihole].resize(2);
37260 poly_file >> dummy_hole;
37261 poly_file >> hole_coordinates[ihole][0];
37262 poly_file >> hole_coordinates[ihole][1];
37268 std::map<unsigned, bool> hole_done;
37272 for (
unsigned i = 0;
i < npolygons-1;
i++)
37275 for (
unsigned h = 0; h < nholes; h++)
37283 const bool hole_in_polygon =
37284 this->is_point_inside_polygon_helper(inner_vertex_coordinates[
i],
37288 if (hole_in_polygon)
37291 hole_done[h] =
true;
37294 index_hole_of_internal_polygon[
i] = h;
37306 if (hole_done.size() != npolygons-1)
37308 std::ostringstream error_message;
37310 <<
"Not all the holes were associated to an internal closed boundary\n"
37311 <<
"Only ("<<hole_done.size()<<
") holes were assigned for a total of\n"
37312 <<
"(" << npolygons-1 <<
") internal closed boundaries.\n"
37313 <<
"You can check the generated mesh by calling the output() method\n"
37314 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37316 OOMPH_CURRENT_FUNCTION,
37317 OOMPH_EXCEPTION_LOCATION);
37322 for (
unsigned ihole = 0; ihole < nholes; ihole++)
37325 const unsigned index_hole = index_hole_of_internal_polygon[ihole];
37330 if (index_hole != ihole)
37332 std::ostringstream error_message;
37334 <<
"The hole vertices coordinates are not listed in the same order\n"
37335 <<
"as the nodes that define the internal closed boundaries.\n"
37336 <<
"This may lead to problems in case that the holes coordinates\n"
37337 <<
"were no properly assigned to the internal closed boundaries.\n"
37338 <<
"You can check the generated mesh by calling the output() method\n"
37339 <<
"from the mesh object '(problem.mesh_pt()->output(string))'\n\n";
37341 OOMPH_CURRENT_FUNCTION,
37342 OOMPH_EXCEPTION_LOCATION);
37347 this->Internal_polygon_pt[ihole]->internal_point() =
37348 hole_coordinates[index_hole];
37352 poly_file.ignore(80,
'\n');
37362 getline(poly_file, regions_info_string);
37366 if (isdigit(regions_info_string.c_str()[0]))
37368 nregions = std::atoi(regions_info_string.c_str());
37376 std::map<unsigned, Vector<double> > regions_coordinates;
37379 unsigned dummy_region;
37381 unsigned region_id;
37384 for(
unsigned iregion=0;iregion<nregions;iregion++)
37388 poly_file >> dummy_region;
37389 poly_file >> tmp_region_coordinates[0];
37390 poly_file >> tmp_region_coordinates[1];
37391 poly_file >> region_id;
37392 regions_coordinates[region_id].resize(2);
37393 regions_coordinates[region_id][0] = tmp_region_coordinates[0];
37394 regions_coordinates[region_id][1] = tmp_region_coordinates[1];
37397 poly_file.ignore(80,
'\n');
37400 if (region_id == 0)
37402 std::ostringstream error_message;
37403 error_message <<
"Please use another region id different from zero.\n"
37404 <<
"It is internally used as the default region number.\n";
37406 OOMPH_CURRENT_FUNCTION,
37407 OOMPH_EXCEPTION_LOCATION);
37413 this->Regions_coordinates = regions_coordinates;
37423 template <
class ELEMENT>
37429 unsigned update_was_performed =
false;
37431 const unsigned nele = this->nelement();
37442 get_face_mesh_representation(polygon_pt,face_mesh_pt);
37450 unsigned n_polyline = polygon_pt->
npolyline();
37453 for(
unsigned p = 0; p < n_polyline; p++)
37466 std::set<Vector<double> > vertex_nodes;
37477 #ifdef OOMPH_HAS_MPI
37507 const unsigned nface_element = face_mesh_pt[p]->nelement();
37514 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
37516 for(
unsigned ef=0;ef<nface_element;++ef)
37518 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
37519 #ifdef OOMPH_HAS_MPI
37521 if (this->is_mesh_distributed() && ele_face_pt->
is_halo())
37525 non_halo_face_element_pt.push_back(ele_face_pt);
37526 face_element_index_on_boundary[ele_face_pt] = ef;
37530 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
37533 std::map<FiniteElement*,bool> face_element_done;
37536 unsigned nsorted_face_elements = 0;
37538 #ifdef OOMPH_HAS_MPI
37540 unsigned nsub_boundaries = 0;
37541 #endif // #ifdef OOMPH_HAS_MPI
37545 while(nsorted_face_elements < nnon_halo_face_element)
37550 bool found_initial_face_element =
false;
37553 unsigned iface = 0;
37554 for (iface = 0; iface < nnon_halo_face_element; iface++)
37556 ele_face_pt = non_halo_face_element_pt[iface];
37558 if (!face_element_done[ele_face_pt])
37561 found_initial_face_element =
true;
37563 nsorted_face_elements++;
37570 if (!found_initial_face_element)
37572 std::ostringstream error_message;
37574 <<
"Could not find an initial face element for the current segment\n";
37577 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37578 OOMPH_EXCEPTION_LOCATION);
37585 std::set<Vector<double> > local_vertex_nodes;
37593 std::set<Vector<double> > sorted_target_areas;
37603 unsigned nnode = ele_face_pt->
nnode();
37607 vertex_coord[0] = bound_left[0];
37610 for(
unsigned i=0;
i<2;
i++)
37612 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
37614 local_vertex_nodes.insert(vertex_coord);
37618 ele_face_pt->
node_pt(nnode-1)->
37619 get_coordinates_on_boundary(bound,bound_right);
37620 vertex_coord[0] = bound_right[0];
37623 for(
unsigned i=0;
i<2;
i++)
37625 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
37627 local_vertex_nodes.insert(vertex_coord);
37631 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
37634 face_element_done[ele_face_pt] =
true;
37646 zeta_target_area_values[0] =
37647 std::min(bound_left[0], bound_right[0]);
37650 unsigned ef = face_element_index_on_boundary[ele_face_pt];
37652 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
37655 bool found_global_element_index =
false;
37657 for (
unsigned eg = 0 ; eg < nele; eg++)
37660 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
37664 if (el_pt == el_compare_pt)
37666 zeta_target_area_values[1] = target_area[eg];
37668 found_global_element_index =
true;
37675 if (!found_global_element_index)
37677 std::ostringstream error_message;
37679 <<
"The global index for the ("<< ef <<
")-th face element "
37680 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37682 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37683 OOMPH_EXCEPTION_LOCATION);
37688 sorted_target_areas.insert(zeta_target_area_values);
37693 bool face_element_added =
false;
37703 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
37705 face_element_added =
false;
37706 ele_face_pt = non_halo_face_element_pt[iiface];
37707 if (!face_element_done[ele_face_pt])
37710 nnode = ele_face_pt->nnode();
37711 Node* left_node_pt = ele_face_pt->node_pt(0);
37712 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
37714 if (left_node_pt == first_node_pt)
37716 first_node_pt = right_node_pt;
37717 face_element_added =
true;
37719 else if (left_node_pt == last_node_pt)
37721 last_node_pt = right_node_pt;
37722 face_element_added =
true;
37724 else if (right_node_pt == first_node_pt)
37726 first_node_pt = left_node_pt;
37727 face_element_added =
true;
37729 else if (right_node_pt == last_node_pt)
37731 last_node_pt = left_node_pt;
37732 face_element_added =
true;
37735 if (face_element_added)
37740 vertex_coord[0] = bound_left[0];
37743 for(
unsigned i=0;
i<2;
i++)
37745 vertex_coord[
i+1] = left_node_pt->
x(
i);
37747 local_vertex_nodes.insert(vertex_coord);
37752 vertex_coord[0] = bound_right[0];
37755 for(
unsigned i=0;
i<2;
i++)
37757 vertex_coord[
i+1] = right_node_pt->
x(
i);
37759 local_vertex_nodes.insert(vertex_coord);
37763 face_element_done[ele_face_pt] =
true;
37764 nsorted_face_elements++;
37772 zeta_target_area_values[0] =
37773 std::min(bound_left[0], bound_right[0]);
37776 ef = face_element_index_on_boundary[ele_face_pt];
37777 FiniteElement *lel_pt = this->boundary_element_pt(bound, ef);
37780 found_global_element_index =
false;
37782 for (
unsigned eg = 0 ; eg < nele; eg++)
37785 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
37789 if (lel_pt == lel_compare_pt)
37791 zeta_target_area_values[1] = target_area[eg];
37793 found_global_element_index =
true;
37800 if (!found_global_element_index)
37802 std::ostringstream error_message;
37804 <<
"The global index for the ("<< ef <<
")-th face element "
37805 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
37807 "RefineableTriangleMesh::update_polygon_using_elements_area()",
37808 OOMPH_EXCEPTION_LOCATION);
37813 sorted_target_areas.insert(zeta_target_area_values);
37820 }
while(face_element_added &&
37821 (nsorted_face_elements < nnon_halo_face_element));
37829 const unsigned nlocal_nodes = local_vertex_nodes.size();
37831 local_tmp_vector_vertex_node.resize(nlocal_nodes);
37834 unsigned counter = 0;
37835 std::set<Vector<double> >::iterator it_vertex;
37836 for (it_vertex = local_vertex_nodes.begin();
37837 it_vertex != local_vertex_nodes.end();
37840 local_tmp_vector_vertex_node[counter].resize(3);
37841 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
37842 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
37843 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
37849 const unsigned ntarget_areas = sorted_target_areas.size();
37850 tmp_sorted_target_areas.resize(ntarget_areas);
37852 std::set<Vector<double> >::iterator it_area;
37853 for(it_area = sorted_target_areas.begin();
37854 it_area != sorted_target_areas.end();
37857 tmp_sorted_target_areas[counter] = (*it_area)[1];
37862 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
37864 std::ostringstream error_message;
37866 <<
"The boundary (" << bound <<
") was split during the "
37867 <<
"distribution process.\n"
37868 <<
"The problem is in the association of the target areas with the\n"
37869 <<
"elements that gave rise to the vertex coordinates.\n"
37870 <<
"The number of local nodes (" << nlocal_nodes
37871 <<
"), on the 'sub-polyline', is not\n"
37872 <<
"according with the number of target "
37873 <<
"areas ("<< ntarget_areas <<
")\nfor that number of nodes.\n"
37874 <<
"The target areas number MUST be equal to the number of\n"
37875 <<
"local nodes minus one\n\n";
37877 OOMPH_CURRENT_FUNCTION,
37878 OOMPH_EXCEPTION_LOCATION);
37889 double unrefinement_tolerance=
37893 bool unrefinement_applied =
37894 unrefine_boundary_constrained_by_target_area(
37895 bound, chunk, local_tmp_vector_vertex_node,
37896 unrefinement_tolerance, tmp_sorted_target_areas);
37899 double refinement_tolerance=
37903 bool refinement_applied =
37904 refine_boundary_constrained_by_target_area(
37905 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
37906 refinement_tolerance, tmp_sorted_target_areas);
37910 local_vertex_nodes.clear();
37915 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
37916 for (
unsigned i = 0;
i < nnew_nodes;
i++)
37918 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
37919 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
37920 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
37921 vertex_nodes.insert(vertex_coord);
37922 local_vertex_nodes.insert(vertex_coord);
37927 update_was_performed = (unrefinement_applied || refinement_applied);
37929 #ifdef OOMPH_HAS_MPI
37930 if (this->is_mesh_distributed())
37934 sub_vertex_nodes.push_back(local_vertex_nodes);
37943 unsigned npoly_vertex = vertex_nodes.size();
37946 tmp_vector_vertex_node.resize(npoly_vertex);
37947 unsigned count = 0;
37948 for(std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
37949 it!=vertex_nodes.end(); ++it)
37951 tmp_vector_vertex_node[count].resize(3);
37952 tmp_vector_vertex_node[count][0] = (*it)[0];
37953 tmp_vector_vertex_node[count][1] = (*it)[1];
37954 tmp_vector_vertex_node[count][2] = (*it)[2];
37958 #ifdef OOMPH_HAS_MPI
37961 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
37962 if (nsub_boundaries_set != nsub_boundaries)
37964 std::ostringstream error_message;
37966 <<
"The number of found sub-boundaries and the number of counted\n"
37967 <<
"sub-boundaries are different:\n"
37968 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
37969 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
37971 OOMPH_CURRENT_FUNCTION,
37972 OOMPH_EXCEPTION_LOCATION);
37977 if (this->is_mesh_distributed() && nsub_boundaries > 1)
37980 this->Boundary_was_splitted[bound] =
true;
37982 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
37983 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
37986 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
37987 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
37988 unsigned subcount = 0;
37989 std::set<Vector<double> >::iterator subit;
37990 for(subit = sub_vertex_nodes[isub].begin();
37991 subit != sub_vertex_nodes[isub].end(); ++subit)
37993 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
37994 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
37995 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
37996 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
38002 #endif // OOMPH_HAS_MPI
38006 unsigned n_vertex=tmp_vector_vertex_node.size();
38009 vector_vertex_node.resize(n_vertex);
38010 for(
unsigned i=0;
i<n_vertex;
i++)
38012 vector_vertex_node[
i].resize(2);
38013 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
38014 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
38017 #ifdef OOMPH_HAS_MPI
38020 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38025 sub_vector_vertex_node.resize(nsub_boundaries);
38026 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38028 const unsigned subn_vertex =
38029 sub_tmp_vector_vertex_node[isub].size();
38031 sub_vector_vertex_node[isub].resize(subn_vertex);
38032 for(
unsigned i=0;
i<subn_vertex;
i++)
38034 sub_vector_vertex_node[isub][
i].resize(2);
38035 sub_vector_vertex_node[isub][
i][0]=
38036 sub_tmp_vector_vertex_node[isub][
i][1];
38037 sub_vector_vertex_node[isub][
i][1]=
38038 sub_tmp_vector_vertex_node[isub][
i][2];
38048 #endif // OOMPH_HAS_MPI
38053 #ifdef OOMPH_HAS_MPI
38057 if (!this->is_mesh_distributed())
38064 unsigned n_prev_vertex =
38066 final_vertex_of_previous_segment =
38068 vertex_coordinate(n_prev_vertex-1);
38070 unsigned prev_seg_boundary_id =
38075 double error = 0.0;
38076 for(
unsigned i=0;
i<2;
i++)
38078 const double dist =
38079 final_vertex_of_previous_segment[
i] -
38080 (*vector_vertex_node.begin())[
i];
38081 error += dist*dist;
38083 error = sqrt(error);
38091 double rev_error = 0.0;
38092 for(
unsigned i=0;
i<2;
i++)
38094 const double dist =
38095 final_vertex_of_previous_segment[
i] -
38096 (*--vector_vertex_node.end())[
i];
38097 rev_error += dist*dist;
38099 rev_error = sqrt(rev_error);
38113 initial_vertex_of_previous_segment =
38115 vertex_coordinate(0);
38117 unsigned prev_seg_boundary_id =
38122 double error = 0.0;
38123 for(
unsigned i=0;
i<2;
i++)
38125 const double dist =
38126 initial_vertex_of_previous_segment[
i] -
38127 (*vector_vertex_node.begin())[
i];
38128 error += dist*dist;
38130 error = sqrt(error);
38138 double rev_error = 0.0;
38139 for(
unsigned i=0;
i<2;
i++)
38141 const double dist =
38142 initial_vertex_of_previous_segment[
i] -
38143 (*--vector_vertex_node.end())[
i];
38144 rev_error += dist*dist;
38146 rev_error = sqrt(rev_error);
38152 std::ostringstream error_stream;
38154 <<
"The distance between the first node of the current\n"
38155 <<
"line segment (boundary "<<bound<<
") and either end of "
38156 <<
"the previous line segment\n"
38157 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than "
38158 <<
"the desired tolerance "
38161 <<
"This suggests that the polylines defining the "
38163 <<
"representation are not properly ordered.\n"
38164 <<
"Fail on last vertex of polyline: ("
38165 << prev_seg_boundary_id <<
") and\n"
38166 <<
"first vertex of polyline (" << bound <<
").\n"
38167 <<
"This should have failed when first trying to "
38168 <<
"construct the\npolygon.\n";
38170 OOMPH_CURRENT_FUNCTION,
38171 OOMPH_EXCEPTION_LOCATION);
38178 std::reverse(vector_vertex_node.begin(),
38179 vector_vertex_node.end());
38193 std::ostringstream error_stream;
38195 <<
"The distance between the first node of the current\n"
38196 <<
"line segment (boundary " << bound <<
") and either end of "
38197 <<
"the previous line segment\n"
38198 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
38199 <<
"desired tolerance " <<
38201 <<
"This suggests that the polylines defining the polygonal\n"
38202 <<
"representation are not properly ordered.\n"
38203 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
38204 <<
") and\nfirst vertex of polyline ("<<bound <<
").\n"
38205 <<
"This should have failed when first trying to construct"
38206 <<
" the polygon.\n";
38208 OOMPH_CURRENT_FUNCTION,
38209 OOMPH_EXCEPTION_LOCATION);
38215 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
38233 n_vertex = vector_vertex_node.size();
38245 double unrefinement_tolerance=
38249 double refinement_tolerance=
38260 #ifdef OOMPH_HAS_MPI
38263 if (this->is_mesh_distributed())
38269 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38270 tmp_curve_section_pt);
38278 this->copy_connection_information(polygon_pt->
polyline_pt(p),
38279 tmp_curve_section_pt);
38285 bool delete_it_on_destructor =
false;
38287 std::set<TriangleMeshCurveSection*>::iterator it =
38290 if (it!=this->Free_curve_section_pt.end())
38292 this->Free_curve_section_pt.erase(it);
38294 delete_it_on_destructor =
true;
38304 if (delete_it_on_destructor)
38309 #ifdef OOMPH_HAS_MPI
38312 if (this->is_mesh_distributed() && nsub_boundaries > 1)
38318 this->Boundary_subpolylines[bound].clear();
38321 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
38322 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
38330 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
38342 #endif // OOMPH_HAS_MPI
38346 delete mesh_geom_obj_pt;
38351 for(
unsigned p=0;p<n_polyline;p++)
38353 face_mesh_pt[p]->flush_node_storage();
38354 delete face_mesh_pt[p];
38357 return update_was_performed;
38365 template <
class ELEMENT>
38371 unsigned update_was_performed =
false;
38373 const unsigned nele = this->nelement();
38384 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
38392 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
38395 for(
unsigned cs = 0; cs < ncurve_section; cs++)
38406 const unsigned bound =
38410 const unsigned chunk =
38420 const unsigned nface_element = face_mesh_pt[cs]->nelement();
38428 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
38431 std::map<FiniteElement*,bool> face_element_done;
38433 for(
unsigned ef = 0; ef < nface_element; ++ef)
38435 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
38440 #ifdef OOMPH_HAS_MPI
38441 if (this->is_mesh_distributed())
38444 if (ele_face_pt->
is_halo()) {
continue;}
38449 if (!face_element_done[ele_face_pt])
38454 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
38456 face_element_index_on_boundary[ele_face_pt] = ef;
38458 face_element_done[ele_face_pt] =
true;
38460 const unsigned nnodes = ele_face_pt->nnode();
38463 Node* left_node_pt = ele_face_pt->node_pt(0);
38464 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
38468 bool found_other_side_face_ele =
false;
38470 for (
unsigned iface = 0; iface < nface_element; iface++)
38474 face_mesh_pt[cs]->finite_element_pt(iface);
38476 if (!face_element_done[cele_face_pt])
38478 Node* cleft_node_pt = cele_face_pt->node_pt(0);
38479 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
38481 if ((left_node_pt == cleft_node_pt &&
38482 right_node_pt == cright_node_pt) ||
38483 (left_node_pt == cright_node_pt &&
38484 right_node_pt == cleft_node_pt))
38487 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
38489 face_element_done[cele_face_pt] =
true;
38491 face_element_index_on_boundary[cele_face_pt] = iface;
38494 found_other_side_face_ele =
true;
38502 if (!found_other_side_face_ele)
38504 std::ostringstream error_message;
38506 <<
"The face element at the other side of the boundary ("
38507 << bound <<
") was not found!!\n"
38508 <<
"These are the nodes of the face element:\n"
38509 <<
"("<<left_node_pt->
x(0)<<
", "<<left_node_pt->
x(1)<<
") "
38510 <<
"and ("<<right_node_pt->
x(0)<<
","<<right_node_pt->
x(1)<<
")\n\n";
38512 "RefineableTriangleMesh::update_open_curve_using_elements_area()",
38513 OOMPH_EXCEPTION_LOCATION);
38522 face_element_done.clear();
38527 std::set<Vector<double> > vertex_nodes;
38538 #ifdef OOMPH_HAS_MPI
38543 std::vector<bool> internal_to_shared_boundary;
38563 #endif // #ifdef OOMPH_HAS_MPI
38570 unsigned nsorted_face_elements = 0;
38572 #ifdef OOMPH_HAS_MPI
38574 unsigned nsub_boundaries = 0;
38575 #endif // #ifdef OOMPH_HAS_MPI
38578 const unsigned nnon_halo_doubled_face_ele =
38579 non_halo_doubled_face_element_pt.size();
38583 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
38589 bool found_initial_face_element =
false;
38595 bool both_root_face_elements_are_nonhalo =
false;
38597 unsigned iface = 0;
38598 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
38600 ele_face_pt = non_halo_doubled_face_element_pt[iface];
38602 if (!face_element_done[ele_face_pt])
38605 face_element_done[ele_face_pt] =
true;
38607 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
38609 face_element_done[repeated_ele_face_pt] =
true;
38611 #ifdef OOMPH_HAS_MPI
38612 if (!repeated_ele_face_pt->
is_halo())
38613 {both_root_face_elements_are_nonhalo =
true;}
38614 #endif // #ifdef OOMPH_HAS_MPI
38618 nsorted_face_elements+=2;
38622 found_initial_face_element =
true;
38629 if (!found_initial_face_element)
38631 std::ostringstream error_message;
38633 <<
"Could not find an initial face element for the current segment\n";
38635 OOMPH_CURRENT_FUNCTION,
38636 OOMPH_EXCEPTION_LOCATION);
38643 std::set<Vector<double> > local_vertex_nodes;
38651 std::set<Vector<double> > sorted_target_areas;
38661 const unsigned nnode = ele_face_pt->
nnode();
38665 vertex_coord[0] = bound_left[0];
38668 for(
unsigned i=0;
i<2;
i++)
38670 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
38672 local_vertex_nodes.insert(vertex_coord);
38678 vertex_coord[0] = bound_right[0];
38681 for(
unsigned i=0;
i<2;
i++)
38683 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
38685 local_vertex_nodes.insert(vertex_coord);
38689 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
38701 zeta_target_area_values[0] = std::min(bound_left[0], bound_right[0]);
38704 const unsigned ef = face_element_index_on_boundary[ele_face_pt];
38706 FiniteElement *el_pt = this->boundary_element_pt(bound, ef);
38707 double target_area_face_element = 0.0;
38710 bool found_global_element_index =
false;
38712 for (
unsigned eg = 0 ; eg < nele; eg++)
38715 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38719 if (el_pt == el_compare_pt)
38721 target_area_face_element = target_area[eg];
38723 found_global_element_index =
true;
38730 if (!found_global_element_index)
38732 std::ostringstream error_message;
38734 <<
"The global index for the ("<< ef <<
")-th face element "
38735 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38737 OOMPH_CURRENT_FUNCTION,
38738 OOMPH_EXCEPTION_LOCATION);
38743 const unsigned ref = face_element_index_on_boundary[repeated_ele_face_pt];
38744 FiniteElement *rel_pt = this->boundary_element_pt(bound, ref);
38745 double target_area_repeated_face_element = 0.0;
38748 bool found_global_repeated_element_index =
false;
38750 for (
unsigned eg = 0 ; eg < nele; eg++)
38753 FiniteElement *el_compare_pt = this->finite_element_pt(eg);
38757 if (rel_pt == el_compare_pt)
38759 target_area_repeated_face_element = target_area[eg];
38761 found_global_repeated_element_index =
true;
38768 if (!found_global_repeated_element_index)
38770 std::ostringstream error_message;
38772 <<
"The global index for the ("<< ref <<
")-th face element "
38773 <<
"on\nthe ("<< bound <<
")-th boundary was not found (repeated "
38774 <<
"face element)!!!";
38776 OOMPH_CURRENT_FUNCTION,
38777 OOMPH_EXCEPTION_LOCATION);
38783 zeta_target_area_values[1]=std::min(target_area_face_element,
38784 target_area_repeated_face_element);
38787 sorted_target_areas.insert(zeta_target_area_values);
38792 bool face_element_added =
false;
38802 for (
unsigned iiface=iface;
38803 iiface<nnon_halo_doubled_face_ele;iiface+=2)
38805 face_element_added =
false;
38806 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
38813 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38814 bool both_face_elements_are_nonhalo =
false;
38816 #ifdef OOMPH_HAS_MPI
38817 if (!repeated_ele_face_pt->
is_halo())
38818 {both_face_elements_are_nonhalo =
true;}
38819 #endif // #ifdef OOMPH_HAS_MPI
38821 if (!face_element_done[ele_face_pt] &&
38822 (both_face_elements_are_nonhalo ==
38823 both_root_face_elements_are_nonhalo))
38826 const unsigned nlnode = ele_face_pt->
nnode();
38828 Node* right_node_pt = ele_face_pt->
node_pt(nlnode-1);
38830 if (left_node_pt == first_node_pt)
38832 first_node_pt = right_node_pt;
38833 face_element_added =
true;
38835 else if (left_node_pt == last_node_pt)
38837 last_node_pt = right_node_pt;
38838 face_element_added =
true;
38840 else if (right_node_pt == first_node_pt)
38842 first_node_pt = left_node_pt;
38843 face_element_added =
true;
38845 else if (right_node_pt == last_node_pt)
38847 last_node_pt = left_node_pt;
38848 face_element_added =
true;
38851 if (face_element_added)
38856 vertex_coord[0] = bound_left[0];
38859 for(
unsigned i=0;
i<2;
i++)
38861 vertex_coord[
i+1] = left_node_pt->
x(
i);
38863 local_vertex_nodes.insert(vertex_coord);
38868 vertex_coord[0] = bound_right[0];
38871 for(
unsigned i=0;
i<2;
i++)
38873 vertex_coord[
i+1] = right_node_pt->
x(
i);
38875 local_vertex_nodes.insert(vertex_coord);
38879 face_element_done[ele_face_pt] =
true;
38882 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
38883 face_element_done[repeated_ele_face_pt] =
true;
38885 nsorted_face_elements+=2;
38893 zeta_target_area_values[0] =
38894 std::min(bound_left[0], bound_right[0]);
38897 const unsigned lef = face_element_index_on_boundary[ele_face_pt];
38898 FiniteElement *lel_pt = this->boundary_element_pt(bound, lef);
38901 found_global_element_index =
false;
38903 for (
unsigned eg = 0 ; eg < nele; eg++)
38906 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38910 if (lel_pt == lel_compare_pt)
38912 target_area_face_element = target_area[eg];
38914 found_global_element_index =
true;
38921 if (!found_global_element_index)
38923 std::ostringstream error_message;
38925 <<
"The global index for the ("<< lef <<
")-th face element "
38926 <<
"on\nthe ("<< bound <<
")-th boundary was not found!!!";
38928 OOMPH_CURRENT_FUNCTION,
38929 OOMPH_EXCEPTION_LOCATION);
38934 const unsigned rlef =
38935 face_element_index_on_boundary[repeated_ele_face_pt];
38936 FiniteElement *rlel_pt = this->boundary_element_pt(bound, rlef);
38939 found_global_repeated_element_index =
false;
38941 for (
unsigned eg = 0 ; eg < nele; eg++)
38944 FiniteElement *lel_compare_pt = this->finite_element_pt(eg);
38948 if (rlel_pt == lel_compare_pt)
38950 target_area_repeated_face_element = target_area[eg];
38952 found_global_repeated_element_index =
true;
38959 if (!found_global_repeated_element_index)
38961 std::ostringstream error_message;
38963 <<
"The global index for the ("<< rlef <<
")-th face element "
38964 <<
"on\nthe ("<< bound <<
")-th boundary was not found "
38965 <<
"(repeated face element)!!!";
38967 OOMPH_CURRENT_FUNCTION,
38968 OOMPH_EXCEPTION_LOCATION);
38974 zeta_target_area_values[1] =
38975 std::min(target_area_face_element,
38976 target_area_repeated_face_element);
38979 sorted_target_areas.insert(zeta_target_area_values);
38986 }
while(face_element_added &&
38987 (nsorted_face_elements < nnon_halo_doubled_face_ele));
38995 const unsigned nlocal_nodes = local_vertex_nodes.size();
38997 local_tmp_vector_vertex_node.resize(nlocal_nodes);
39000 unsigned counter = 0;
39001 std::set<Vector<double> >::iterator it_vertex;
39002 for (it_vertex = local_vertex_nodes.begin();
39003 it_vertex != local_vertex_nodes.end();
39006 local_tmp_vector_vertex_node[counter].resize(3);
39007 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
39008 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
39009 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
39015 const unsigned ntarget_areas = sorted_target_areas.size();
39016 tmp_sorted_target_areas.resize(ntarget_areas);
39018 std::set<Vector<double> >::iterator it_area;
39019 for(it_area = sorted_target_areas.begin();
39020 it_area != sorted_target_areas.end();
39023 tmp_sorted_target_areas[counter] = (*it_area)[1];
39028 if (nlocal_nodes > 0 && (ntarget_areas != nlocal_nodes - 1) )
39030 std::ostringstream error_message;
39032 <<
"The boundary (" << bound <<
") was split during the "
39033 <<
"distribution process.\n"
39034 <<
"The problem comes when associating the target areas with the "
39035 <<
"elements that gave\nrise to the vertex coordinates.\n"
39036 <<
"The number of local nodes on the 'sub-polyline' ("
39037 << nlocal_nodes <<
") is not according with the number of target\n"
39038 <<
"areas ("<< ntarget_areas <<
") for that number of nodes.\n"
39039 <<
"The target areas number must be equal to the number of nodes-1\n";
39041 OOMPH_CURRENT_FUNCTION,
39042 OOMPH_EXCEPTION_LOCATION);
39049 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
39050 local_tmp_vector_vertex_node[0][2])
39052 std::reverse(local_tmp_vector_vertex_node.begin(),
39053 local_tmp_vector_vertex_node.end());
39054 std::reverse(tmp_sorted_target_areas.begin(),
39055 tmp_sorted_target_areas.end());
39057 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
39058 local_tmp_vector_vertex_node[0][2])
39060 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
39061 local_tmp_vector_vertex_node[0][1])
39063 std::reverse(local_tmp_vector_vertex_node.begin(),
39064 local_tmp_vector_vertex_node.end());
39065 std::reverse(tmp_sorted_target_areas.begin(),
39066 tmp_sorted_target_areas.end());
39077 double unrefinement_tolerance=
39081 bool unrefinement_applied =
39082 unrefine_boundary_constrained_by_target_area(
39083 bound, chunk, local_tmp_vector_vertex_node,
39084 unrefinement_tolerance, tmp_sorted_target_areas);
39087 double refinement_tolerance=
39091 bool refinement_applied =
39092 refine_boundary_constrained_by_target_area(
39093 mesh_geom_obj_pt, local_tmp_vector_vertex_node,
39094 refinement_tolerance, tmp_sorted_target_areas);
39098 local_vertex_nodes.clear();
39103 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
39104 for (
unsigned i = 0;
i < nnew_nodes;
i++)
39106 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
39107 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
39108 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
39109 vertex_nodes.insert(vertex_coord);
39110 local_vertex_nodes.insert(vertex_coord);
39115 update_was_performed = (unrefinement_applied || refinement_applied);
39117 #ifdef OOMPH_HAS_MPI
39118 if (this->is_mesh_distributed())
39123 sub_vertex_nodes.push_back(local_vertex_nodes);
39129 if (both_root_face_elements_are_nonhalo)
39130 {internal_to_shared_boundary.push_back(
false);}
39132 {internal_to_shared_boundary.push_back(
true);}
39142 const unsigned npoly_vertex = vertex_nodes.size();
39143 tmp_vector_vertex_node.resize(npoly_vertex);
39144 unsigned count = 0;
39145 for (std::set<
Vector<double> >::iterator it = vertex_nodes.begin();
39146 it!=vertex_nodes.end(); ++it)
39148 tmp_vector_vertex_node[count].resize(3);
39149 tmp_vector_vertex_node[count][0] = (*it)[0];
39150 tmp_vector_vertex_node[count][1] = (*it)[1];
39151 tmp_vector_vertex_node[count][2] = (*it)[2];
39155 #ifdef OOMPH_HAS_MPI
39160 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
39161 const unsigned ninternal_to_shared_boundaries =
39162 internal_to_shared_boundary.size();
39163 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
39165 std::ostringstream error_message;
39167 <<
"The number of found sub-boundaries and the number of marked "
39168 <<
"internal\nboundaries are different\n"
39169 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
39170 <<
"Number of marked internal boundaries: ("
39171 << ninternal_to_shared_boundaries <<
")\n\n";
39173 OOMPH_CURRENT_FUNCTION,
39174 OOMPH_EXCEPTION_LOCATION);
39180 if (nsub_boundaries_set != nsub_boundaries)
39182 std::ostringstream error_message;
39184 <<
"The number of found sub-boundaries and the number of counted\n"
39185 <<
"sub-boundaries are different:\n"
39186 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
39187 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
39189 OOMPH_CURRENT_FUNCTION,
39190 OOMPH_EXCEPTION_LOCATION);
39195 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39198 this->Boundary_was_splitted[bound] =
true;
39201 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
39203 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39206 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
39207 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
39208 unsigned subcount = 0;
39209 std::set<Vector<double> >::iterator subit;
39210 for(subit = sub_vertex_nodes[isub].begin();
39211 subit != sub_vertex_nodes[isub].end(); ++subit)
39213 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
39214 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
39215 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
39216 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
39222 #endif // OOMPH_HAS_MPI
39226 unsigned n_vertex=tmp_vector_vertex_node.size();
39229 vector_vertex_node.resize(n_vertex);
39230 for(
unsigned i=0;
i<n_vertex;
i++)
39232 vector_vertex_node[
i].resize(2);
39233 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
39234 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
39237 #ifdef OOMPH_HAS_MPI
39240 if (this->is_mesh_distributed() && nsub_boundaries > 1)
39245 sub_vector_vertex_node.resize(nsub_boundaries);
39246 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39248 const unsigned subn_vertex =
39249 sub_tmp_vector_vertex_node[isub].size();
39251 sub_vector_vertex_node[isub].resize(subn_vertex);
39252 for(
unsigned i=0;
i<subn_vertex;
i++)
39254 sub_vector_vertex_node[isub][
i].resize(2);
39255 sub_vector_vertex_node[isub][
i][0]=
39256 sub_tmp_vector_vertex_node[isub][
i][1];
39257 sub_vector_vertex_node[isub][
i][1]=
39258 sub_tmp_vector_vertex_node[isub][
i][2];
39268 #endif // OOMPH_HAS_MPI
39273 #ifdef OOMPH_HAS_MPI
39277 if (!this->is_mesh_distributed())
39284 unsigned n_prev_vertex =
39286 final_vertex_of_previous_segment =
39288 vertex_coordinate(n_prev_vertex-1);
39290 unsigned prev_seg_boundary_id =
39295 double error = 0.0;
39296 for(
unsigned i=0;
i<2;
i++)
39298 const double dist =
39299 final_vertex_of_previous_segment[
i] -
39300 (*vector_vertex_node.begin())[
i];
39301 error += dist*dist;
39303 error = sqrt(error);
39311 double rev_error = 0.0;
39312 for(
unsigned i=0;
i<2;
i++)
39314 const double dist =
39315 final_vertex_of_previous_segment[
i] -
39316 (*--vector_vertex_node.end())[
i];
39317 rev_error += dist*dist;
39319 rev_error = sqrt(rev_error);
39333 initial_vertex_of_previous_segment =
39336 unsigned prev_seg_boundary_id =
39341 double error = 0.0;
39342 for(
unsigned i=0;
i<2;
i++)
39344 const double dist =
39345 initial_vertex_of_previous_segment[
i] -
39346 (*vector_vertex_node.begin())[
i];
39347 error += dist*dist;
39349 error = sqrt(error);
39357 double rev_error = 0.0;
39358 for(
unsigned i=0;
i<2;
i++)
39360 const double dist =
39361 initial_vertex_of_previous_segment[
i] -
39362 (*--vector_vertex_node.end())[
i];
39363 rev_error += dist*dist;
39365 rev_error = sqrt(rev_error);
39371 std::ostringstream error_stream;
39373 <<
"The distance between the first node of the current\n"
39374 <<
"line segment (boundary "<<bound<<
") and either end of "
39375 <<
"the previous line segment\n"
39376 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than"
39377 <<
" the desired tolerance " <<
39379 <<
"This suggests that the polylines defining the polygonal\n"
39380 <<
"representation are not properly ordered.\n"
39381 <<
"Fail on last vertex of polyline: ("
39382 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
39383 <<bound<<
").\nThis should have failed when first trying to "
39384 <<
"construct the\npolygon.\n";
39386 OOMPH_CURRENT_FUNCTION,
39387 OOMPH_EXCEPTION_LOCATION);
39393 std::reverse(vector_vertex_node.begin(),
39394 vector_vertex_node.end());
39407 std::ostringstream error_stream;
39409 <<
"The distance between the first node of the current\n"
39410 <<
"line segment (boundary " << bound <<
") and either end of "
39411 <<
"the previous line segment\n"
39412 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than the "
39413 <<
"desired tolerance " <<
39415 <<
"This suggests that the polylines defining the polygonal\n"
39416 <<
"representation are not properly ordered.\n"
39417 <<
"Fail on last vertex of polyline: ("<<prev_seg_boundary_id
39418 <<
") and\nfirst vertex of polyline (" <<bound <<
").\n"
39419 <<
"This should have failed when first trying to construct\n"
39420 <<
"the polygon.\n";
39422 OOMPH_CURRENT_FUNCTION,
39423 OOMPH_EXCEPTION_LOCATION);
39429 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
39447 n_vertex = vector_vertex_node.size();
39459 double unrefinement_tolerance=
39463 double refinement_tolerance=
39474 #ifdef OOMPH_HAS_MPI
39477 if (this->is_mesh_distributed())
39483 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39484 tmp_curve_section_pt);
39492 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
39493 tmp_curve_section_pt);
39499 bool delete_it_on_destructor =
false;
39501 std::set<TriangleMeshCurveSection*>::iterator it =
39504 if (it!=this->Free_curve_section_pt.end())
39506 this->Free_curve_section_pt.erase(it);
39508 delete_it_on_destructor =
true;
39516 this->Boundary_curve_section_pt[bound] =
39519 if (delete_it_on_destructor)
39524 #ifdef OOMPH_HAS_MPI
39527 if (this->is_mesh_distributed() && nsub_boundaries == 1)
39530 this->Boundary_marked_as_shared_boundary[bound].clear();
39533 this->Boundary_marked_as_shared_boundary[bound].push_back(
39534 internal_to_shared_boundary[0]);
39538 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
39544 this->Boundary_subpolylines[bound].clear();
39546 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
39549 this->Boundary_marked_as_shared_boundary[bound].clear();
39552 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
39553 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
39562 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
39566 this->Boundary_marked_as_shared_boundary[bound][isub] =
39567 internal_to_shared_boundary[isub];
39577 sub_tmp_polyline_pt;
39578 this->copy_connection_information_to_sub_polylines(
39579 tmp_curve_section_pt, tmp_sub_curve_section_pt);
39585 #endif // OOMPH_HAS_MPI
39589 delete mesh_geom_obj_pt;
39594 for(
unsigned p = 0; p < ncurve_section; p++)
39596 face_mesh_pt[p]->flush_node_storage();
39597 delete face_mesh_pt[p];
39600 return update_was_performed;
39604 #ifdef OOMPH_HAS_MPI
39609 template <
class ELEMENT>
39612 &vector_polyline_pt,
39617 unsigned update_was_performed =
false;
39620 const unsigned n_polylines = vector_polyline_pt.size();
39621 for (
unsigned pp = 0; pp < n_polylines; pp++)
39624 const unsigned shd_bnd_id = vector_polyline_pt[pp]->boundary_id();
39627 const unsigned chunk = vector_polyline_pt[pp]->boundary_chunk();
39635 std::map<FiniteElement*, FiniteElement*> face_ele_pt_to_bulk_element_pt;
39644 const unsigned nshared_bound_ele =
39645 this->nshared_boundary_element(shd_bnd_id);
39649 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
39653 this->shared_boundary_element_pt(shd_bnd_id,
e);
39656 int face_index = this->face_index_at_shared_boundary(shd_bnd_id,
e);
39665 face_ele_pt_to_bulk_element_pt[face_ele_pt] = bulk_ele_pt;
39671 nonhalo_shared_face_ele_pt.push_back(face_ele_pt);
39676 halo_shared_face_ele_pt.push_back(face_ele_pt);
39686 std::map<FiniteElement*, bool> shared_face_done;
39689 const unsigned nnonhalo_face_shared_ele =
39690 nonhalo_shared_face_ele_pt.size();
39693 const unsigned nhalo_face_shared_ele =
39694 halo_shared_face_ele_pt.size();
39699 if (nshared_bound_ele / 2 != nnonhalo_face_shared_ele)
39701 std::ostringstream error_message;
39703 <<
"The number of shared boundary elements (" << nshared_bound_ele
39704 <<
") is not the double\nof the number of unsorted NONHALO shared "
39705 <<
"face boundary elements (" << nnonhalo_face_shared_ele <<
")\n"
39706 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39708 OOMPH_CURRENT_FUNCTION,
39709 OOMPH_EXCEPTION_LOCATION);
39714 if (nshared_bound_ele / 2 != nhalo_face_shared_ele)
39716 std::ostringstream error_message;
39718 <<
"The number of shared boundary elements (" << nshared_bound_ele
39719 <<
") is not the double\nof the number of unsorted HALO shared "
39720 <<
"face boundary elements (" << nhalo_face_shared_ele <<
")\n"
39721 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39723 OOMPH_CURRENT_FUNCTION,
39724 OOMPH_EXCEPTION_LOCATION);
39731 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
39734 FiniteElement* nonhalo_face_ele_pt = nonhalo_shared_face_ele_pt[inh];
39737 const unsigned nnodes_nh = nonhalo_face_ele_pt->
nnode();
39739 Node* nh_first_node_pt = nonhalo_face_ele_pt->
node_pt(0);
39740 Node* nh_last_node_pt = nonhalo_face_ele_pt->
node_pt(nnodes_nh-1);
39744 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
39747 FiniteElement* halo_face_ele_pt = halo_shared_face_ele_pt[ih];
39750 if (!shared_face_done[halo_face_ele_pt])
39753 const unsigned nnodes_h = halo_face_ele_pt->nnode();
39755 Node* h_first_node_pt = halo_face_ele_pt->node_pt(0);
39756 Node* h_last_node_pt = halo_face_ele_pt->node_pt(nnodes_h-1);
39760 if (nh_first_node_pt == h_first_node_pt &&
39761 nh_last_node_pt == h_last_node_pt)
39768 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39770 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39773 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39774 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39777 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39780 shared_face_done[nonhalo_face_ele_pt] =
true;
39781 shared_face_done[halo_face_ele_pt] =
true;
39787 else if (nh_first_node_pt == h_last_node_pt &&
39788 nh_last_node_pt == h_first_node_pt)
39795 face_ele_pt_to_bulk_element_pt[nonhalo_face_ele_pt];
39797 face_ele_pt_to_bulk_element_pt[halo_face_ele_pt];
39800 tmp_bulk_element_pt.push_back(nonhalo_bulk_ele_pt);
39801 tmp_bulk_element_pt.push_back(halo_bulk_ele_pt);
39804 unsorted_shared_bulk_ele_pt.push_back(tmp_bulk_element_pt);
39807 shared_face_done[nonhalo_face_ele_pt] =
true;
39808 shared_face_done[halo_face_ele_pt] =
true;
39830 const unsigned nunsorted_shared_bulk_ele =
39831 unsorted_shared_bulk_ele_pt.size();
39835 if (nshared_bound_ele / 2 != nunsorted_shared_bulk_ele)
39837 std::ostringstream error_message;
39839 <<
"The number of shared boundary elements (" << nshared_bound_ele
39840 <<
") is not the double\nof the number of unsorted shared bulk "
39841 <<
"boundary elements (" << nunsorted_shared_bulk_ele <<
")\n"
39842 <<
"for the current boundary ("<< shd_bnd_id <<
")\n\n";
39844 OOMPH_CURRENT_FUNCTION,
39845 OOMPH_EXCEPTION_LOCATION);
39850 if ((nnonhalo_face_shared_ele + nhalo_face_shared_ele) !=
39851 shared_face_done.size())
39853 std::ostringstream error_message;
39855 <<
"The number of DONE shared boundary face elements ("
39856 << shared_face_done.size() <<
") is not the same\n as the sum of"
39857 <<
"the nonhalo face shared boundary elements ("
39858 << nnonhalo_face_shared_ele <<
")\nand the halo face shared "
39859 <<
"boundary elements ("<< nhalo_face_shared_ele <<
") for the\n/"
39860 <<
"current boundary (" << shd_bnd_id <<
")\n\n";
39862 OOMPH_CURRENT_FUNCTION,
39863 OOMPH_EXCEPTION_LOCATION);
39868 shared_face_done.clear();
39871 unsigned nsorted_face_ele = 0;
39875 std::list<Node*> sorted_nodes;
39878 std::list<FiniteElement*> sorted_shared_bound_elements_pt;
39881 FiniteElement* root_face_ele_pt = nonhalo_shared_face_ele_pt[0];
39882 nsorted_face_ele++;
39885 shared_face_done[root_face_ele_pt] =
true;
39888 const unsigned nnodes_root = root_face_ele_pt->
nnode();
39889 Node *first_node_pt = root_face_ele_pt->
node_pt(0);
39890 Node *last_node_pt = root_face_ele_pt->
node_pt(nnodes_root-1);
39893 sorted_nodes.push_back(first_node_pt);
39894 sorted_nodes.push_back(last_node_pt);
39897 sorted_shared_bound_elements_pt.push_back(
39898 unsorted_shared_bulk_ele_pt[0][0]);
39899 sorted_shared_bound_elements_pt.push_back(
39900 unsorted_shared_bulk_ele_pt[0][1]);
39903 while (nsorted_face_ele < nnonhalo_face_shared_ele)
39906 bool node_added =
false;
39910 for (
unsigned iface = 1; iface < nnonhalo_face_shared_ele; iface++)
39913 nonhalo_shared_face_ele_pt[iface];
39916 if (!shared_face_done[tmp_shared_face_ele_pt])
39919 const unsigned tmp_nnodes = tmp_shared_face_ele_pt->nnode();
39922 Node* left_node_pt = tmp_shared_face_ele_pt->node_pt(0);
39923 Node* right_node_pt = tmp_shared_face_ele_pt->node_pt(tmp_nnodes-1);
39925 if (left_node_pt == first_node_pt)
39928 sorted_nodes.push_front(right_node_pt);
39929 first_node_pt = right_node_pt;
39933 sorted_shared_bound_elements_pt.push_front(
39934 unsorted_shared_bulk_ele_pt[iface][1]);
39935 sorted_shared_bound_elements_pt.push_front(
39936 unsorted_shared_bulk_ele_pt[iface][0]);
39938 else if (left_node_pt == last_node_pt)
39941 sorted_nodes.push_back(right_node_pt);
39942 last_node_pt = right_node_pt;
39946 sorted_shared_bound_elements_pt.push_back(
39947 unsorted_shared_bulk_ele_pt[iface][0]);
39948 sorted_shared_bound_elements_pt.push_back(
39949 unsorted_shared_bulk_ele_pt[iface][1]);
39951 else if (right_node_pt == first_node_pt)
39954 sorted_nodes.push_front(left_node_pt);
39955 first_node_pt = left_node_pt;
39959 sorted_shared_bound_elements_pt.push_front(
39960 unsorted_shared_bulk_ele_pt[iface][1]);
39961 sorted_shared_bound_elements_pt.push_front(
39962 unsorted_shared_bulk_ele_pt[iface][0]);
39964 else if (right_node_pt == last_node_pt)
39967 sorted_nodes.push_back(left_node_pt);
39968 last_node_pt = left_node_pt;
39972 sorted_shared_bound_elements_pt.push_back(
39973 unsorted_shared_bulk_ele_pt[iface][0]);
39974 sorted_shared_bound_elements_pt.push_back(
39975 unsorted_shared_bulk_ele_pt[iface][1]);
39982 shared_face_done[tmp_shared_face_ele_pt] =
true;
39983 nsorted_face_ele++;
40000 for (
unsigned inh = 0; inh < nnonhalo_face_shared_ele; inh++)
40002 delete nonhalo_shared_face_ele_pt[inh];
40003 nonhalo_shared_face_ele_pt[inh] = 0;
40007 for (
unsigned ih = 0; ih < nhalo_face_shared_ele; ih++)
40009 delete halo_shared_face_ele_pt[ih];
40010 halo_shared_face_ele_pt[ih] = 0;
40018 const unsigned n_nodes = sorted_nodes.size();
40024 unsigned counter = 0;
40025 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
40026 it_nodes != sorted_nodes.end();
40029 polyline_vertices[counter].resize(2);
40030 polyline_vertices[counter][0] = (*it_nodes)->x(0);
40031 polyline_vertices[counter][1] = (*it_nodes)->x(1);
40041 for (std::list<FiniteElement*>::iterator it_ele =
40042 sorted_shared_bound_elements_pt.begin();
40043 it_ele != sorted_shared_bound_elements_pt.end();
40045 {sorted_shared_ele_pt.push_back((*it_ele));}
40048 const unsigned n_shared_target_areas = sorted_shared_ele_pt.size();
40049 Vector<double> sorted_shared_target_areas(n_shared_target_areas);
40052 std::map<std::pair<GeneralisedElement*, unsigned>,
bool> shared_ele_done;
40055 unsigned count_found_shared_element = 0;
40058 const unsigned nele = this->nelement();
40062 for (
unsigned e = 0;
e < nele;
e++)
40067 for (
unsigned s = 0;
s < n_shared_target_areas;
s++)
40072 std::pair<GeneralisedElement*, unsigned> pair_gen_ele_idx =
40073 std::make_pair(current_shared_ele_pt,
s);
40074 if (!shared_ele_done[pair_gen_ele_idx])
40077 if (current_ele_pt == current_shared_ele_pt)
40080 sorted_shared_target_areas[
s] = target_areas[
e];
40082 shared_ele_done[pair_gen_ele_idx] =
true;
40084 count_found_shared_element++;
40090 if (count_found_shared_element == n_shared_target_areas)
40098 if (count_found_shared_element != n_shared_target_areas)
40100 std::ostringstream error_message;
40102 <<
"The number of found target areas ("
40103 << count_found_shared_element <<
") is different from the "
40104 <<
"total number\nof target areas ("
40105 << n_shared_target_areas <<
") in shared boundary ("
40106 << shd_bnd_id <<
")\n\n";
40108 OOMPH_CURRENT_FUNCTION,
40109 OOMPH_EXCEPTION_LOCATION);
40114 const unsigned n_vertices = n_nodes;
40117 const unsigned n_segments = vector_polyline_pt[pp]->nsegment();
40126 if (n_segments != n_vertices-1)
40128 std::ostringstream error_message;
40130 <<
"The number of segments from the current shared polyline "
40131 <<
"(" << n_segments <<
") does not\ncorrespond with the number of "
40132 <<
"sorted vertices (" << n_vertices-1 <<
") of the current shared\n"
40135 OOMPH_CURRENT_FUNCTION,
40136 OOMPH_EXCEPTION_LOCATION);
40141 if (n_segments != n_shared_target_areas/2)
40143 std::ostringstream error_message;
40145 <<
"The number of segments for the current sorting of edges "
40146 <<
"(" << n_segments <<
") is different\nfrom the number of "
40147 <<
"target areas (" << n_shared_target_areas/2 <<
")\n\n";
40149 OOMPH_CURRENT_FUNCTION,
40150 OOMPH_EXCEPTION_LOCATION);
40164 for (
unsigned s = 0;
s < n_segments;
s++)
40167 polyline_target_area[
s] = std::min(sorted_shared_target_areas[
s*2],
40168 sorted_shared_target_areas[(
s*2)+1]);
40175 if (polyline_vertices[n_vertices-1][1] < polyline_vertices[0][1])
40177 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40178 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40180 else if (polyline_vertices[n_vertices-1][1] == polyline_vertices[0][1])
40182 if (polyline_vertices[n_vertices-1][0] < polyline_vertices[0][0])
40184 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
40185 std::reverse(polyline_target_area.begin(), polyline_target_area.end());
40191 bool unrefinement_applied =
false;
40194 if (n_vertices > 3)
40196 unrefinement_applied =
40197 unrefine_shared_boundary_constrained_by_target_area(
40198 shd_bnd_id, chunk, polyline_vertices, polyline_target_area);
40202 bool refinement_applied =
40203 refine_shared_boundary_constrained_by_target_area(polyline_vertices,
40204 polyline_target_area);
40207 update_was_performed |= (unrefinement_applied || refinement_applied);
40221 this->copy_connection_information(curve_section_pt, new_polyline_pt);
40226 bool delete_it_on_destructor =
false;
40230 std::set<TriangleMeshCurveSection*>::iterator it =
40231 this->Free_curve_section_pt.find(curve_section_pt);
40233 if (it!=this->Free_curve_section_pt.end())
40235 this->Free_curve_section_pt.erase(it);
40236 delete curve_section_pt;
40237 delete_it_on_destructor =
true;
40241 vector_polyline_pt[pp] = new_polyline_pt;
40247 this->Boundary_curve_section_pt[shd_bnd_id] = new_curve_section_pt;
40249 if (delete_it_on_destructor)
40251 this->Free_curve_section_pt.insert(new_curve_section_pt);
40256 return update_was_performed;
40259 #endif // #ifdef OOMPH_HAS_MPI
40266 template<
class ELEMENT>
40271 &vector_bnd_vertices,
40272 double &unrefinement_tolerance,
40276 std::set<Vector<double> > no_delete_vertex;
40279 const bool boundary_receive_connections =
40280 this->boundary_connections(b, c, no_delete_vertex);
40284 bool unrefinement_applied =
false;
40287 if (!Do_boundary_unrefinement_constrained_by_target_areas)
40289 return unrefinement_applied;
40303 unsigned n_vertex = vector_bnd_vertices.size();
40306 const double constant_value = 4.0/sqrt(3.0);
40312 for (
unsigned i = 1;
i < n_vertex-1;
i+=2)
40314 if (area_constraint[
i-1] > 0 && area_constraint[
i] > 0)
40316 const double local_zeta_first = vector_bnd_vertices[
i-1][0];
40317 const double local_zeta_last = vector_bnd_vertices[
i+1][0];
40318 const double local_length_zeta =
40319 std::fabs(local_zeta_last-local_zeta_first);
40321 const double x1 = vector_bnd_vertices[
i-1][1];
40322 const double y1 = vector_bnd_vertices[
i-1][2];
40323 const double x2 = vector_bnd_vertices[
i+1][1];
40324 const double y2 = vector_bnd_vertices[
i+1][2];
40325 const double local_length =
40326 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40328 const double x_m = vector_bnd_vertices[
i][1];
40329 const double y_m = vector_bnd_vertices[
i][2];
40331 const double average_area_constraint =
40332 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40336 const double length_side =
40337 sqrt(constant_value*average_area_constraint);
40339 const double length_side_zeta =
40340 (local_length_zeta * length_side) / local_length;
40343 if ((length_side_zeta / local_length_zeta) > 1.0)
40350 double a_x=vector_bnd_vertices[
i-1][1];
40351 double a_y=vector_bnd_vertices[
i-1][2];
40352 double b_x=vector_bnd_vertices[
i][1];
40353 double b_y=vector_bnd_vertices[
i][2];
40354 double c_x=vector_bnd_vertices[
i+1][1];
40355 double c_y=vector_bnd_vertices[
i+1][2];
40362 double e=
a*(a_x+b_x)+b*(a_y+b_y);
40363 double f=c*(a_x+c_x)+d*(a_y+c_y);
40365 double g=2.0*(
a*(c_y-b_y)-b*(c_x-b_x));
40368 if (std::fabs(g)<1.0e-14)
40374 double p_x=(d*
e-b*f)/g;
40375 double p_y=(
a*f-c*
e)/g;
40377 double r=sqrt(pow((a_x-p_x),2)+pow((a_y-p_y),2));
40379 double rhalfca_x=0.5*(a_x-c_x);
40380 double rhalfca_y=0.5*(a_y-c_y);
40382 double halfca_squared=pow(rhalfca_x,2)+pow(rhalfca_y,2);
40384 double sticky_out_bit=r-sqrt(std::fabs((r*r) - halfca_squared));
40389 if ((sticky_out_bit/(2.0*sqrt(halfca_squared)))<
40390 unrefinement_tolerance)
40398 if (do_it && boundary_receive_connections)
40402 no_delete_vertex.begin();
40403 it != no_delete_vertex.end(); it++)
40407 const double x = (*it)[0];
40408 const double y = (*it)[1];
40409 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40410 error = sqrt(error);
40427 vector_bnd_vertices[
i].resize(0);
40441 for(
unsigned i = 0;
i < n_vertex;
i++)
40444 if (vector_bnd_vertices[
i].size()!=0)
40446 compact_vector.push_back(vector_bnd_vertices[
i]);
40452 unsigned nsize_target = area_constraint.size();
40453 if (nsize_target == 1)
40456 compact_area_constraint.push_back(area_constraint[0]);
40460 for(
unsigned i = 1;
i < n_vertex;
i+=2)
40464 if (vector_bnd_vertices[
i].size()!=0)
40466 compact_area_constraint.push_back(area_constraint[
i-1]);
40468 if (
i < nsize_target)
40470 compact_area_constraint.push_back(area_constraint[
i]);
40477 double new_area_constraint =
40478 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40479 compact_area_constraint.push_back(new_area_constraint);
40486 if( n_vertex != compact_vector.size() )
40488 unrefinement_applied =
true;
40492 n_vertex = compact_vector.size();
40493 vector_bnd_vertices.resize(n_vertex);
40494 for(
unsigned i = 0;
i < n_vertex;
i++)
40496 vector_bnd_vertices[
i].resize(3);
40497 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40498 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40499 vector_bnd_vertices[
i][2] = compact_vector[
i][2];
40503 unsigned ntarget_areas = compact_area_constraint.size();
40504 area_constraint.resize(ntarget_areas);
40505 for(
unsigned i = 0;
i < ntarget_areas;
i++)
40507 area_constraint[
i] = compact_area_constraint[
i];
40512 return unrefinement_applied;
40521 template<
class ELEMENT>
40526 &vector_bnd_vertices,
40527 double &refinement_tolerance,
40532 bool refinement_applied =
false;
40535 if (!Do_boundary_refinement_constrained_by_target_areas)
40537 return refinement_applied;
40541 unsigned n_vertex=vector_bnd_vertices.size();
40544 const double constant_value = 4.0/sqrt(3.0);
40554 for (
unsigned i = 0;
i < n_vertex-1;
i++)
40557 new_vector.push_back(vector_bnd_vertices[
i]);
40559 if (area_constraint[
i] > 0)
40561 double local_zeta_first = vector_bnd_vertices[
i][0];
40562 double local_zeta_last = vector_bnd_vertices[
i+1][0];
40563 const double local_length_zeta =
40564 std::fabs(local_zeta_last-local_zeta_first);
40569 if (local_zeta_first > local_zeta_last)
40571 const double tmp_zeta = local_zeta_first;
40572 local_zeta_first = local_zeta_last;
40573 local_zeta_last = tmp_zeta;
40576 const double x1 = vector_bnd_vertices[
i][1];
40577 const double y1 = vector_bnd_vertices[
i][2];
40578 const double x2 = vector_bnd_vertices[
i+1][1];
40579 const double y2 = vector_bnd_vertices[
i+1][2];
40580 const double local_length =
40581 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40584 const double length_side = sqrt(constant_value*area_constraint[
i]);
40585 const double length_side_zeta =
40586 (local_length_zeta * length_side) / local_length;
40589 const double n_seg_double = length_side_zeta/local_length_zeta;
40592 unsigned n_seg = 1;
40595 n_seg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40602 double zeta_increment = (local_length_zeta)/((
double)n_seg);
40606 for(
unsigned s=1;
s<n_seg;
s++)
40609 zeta[0]= local_zeta_first + zeta_increment*double(
s);
40611 mesh_geom_obj_pt->
position(zeta, vertex);
40615 new_node[0]=zeta[0];
40616 new_node[1]=vertex[0];
40617 new_node[2]=vertex[1];
40620 new_vector.push_back(new_node);
40631 new_vector.push_back(vector_bnd_vertices[n_vertex-1]);
40636 n_vertex=new_vector.size();
40637 if( n_vertex != vector_bnd_vertices.size() )
40639 refinement_applied =
true;
40643 vector_bnd_vertices.resize(n_vertex);
40644 for(
unsigned i=0;
i<n_vertex;
i++)
40646 vector_bnd_vertices[
i].resize(3);
40647 vector_bnd_vertices[
i][0]=new_vector[
i][0];
40648 vector_bnd_vertices[
i][1]=new_vector[
i][1];
40649 vector_bnd_vertices[
i][2]=new_vector[
i][2];
40654 return refinement_applied;
40665 template <
class ELEMENT>
40674 std::set<Vector<double> > no_delete_vertex;
40677 const bool boundary_receive_connections =
40678 this->boundary_connections(b, c, no_delete_vertex);
40682 bool unrefinement_applied =
false;
40685 if (!Do_shared_boundary_unrefinement_constrained_by_target_areas)
40687 return unrefinement_applied;
40703 unsigned n_vertex = vector_bnd_vertices.size();
40706 const double constant_value = 4.0/sqrt(3.0);
40712 for (
unsigned i = 1;
i < n_vertex-1;
i+=2)
40716 if (area_constraint[
i-1] > 0 && area_constraint[
i] > 0)
40719 const double x1 = vector_bnd_vertices[
i-1][0];
40720 const double y1 = vector_bnd_vertices[
i-1][1];
40722 const double x2 = vector_bnd_vertices[
i+1][0];
40723 const double y2 = vector_bnd_vertices[
i+1][1];
40726 const double local_length =
40727 sqrt(((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)));
40730 const double x_m = vector_bnd_vertices[
i][0];
40731 const double y_m = vector_bnd_vertices[
i][1];
40734 const double average_area_constraint =
40735 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40739 const double length_side =
40740 sqrt(constant_value*average_area_constraint);
40743 if ((length_side / local_length) > 1.0)
40749 if (do_it && boundary_receive_connections)
40753 no_delete_vertex.begin();
40754 it != no_delete_vertex.end(); it++)
40758 const double x = (*it)[0];
40759 const double y = (*it)[1];
40760 double error = (x_m - x)*(x_m - x) + (y_m - y)*(y_m - y);
40761 error = sqrt(error);
40778 vector_bnd_vertices[
i].resize(0);
40794 for(
unsigned i = 0;
i < n_vertex;
i++)
40797 if (vector_bnd_vertices[
i].size()!=0)
40799 compact_vector.push_back(vector_bnd_vertices[
i]);
40805 unsigned n_area_constraint = area_constraint.size();
40806 if (n_area_constraint == 1)
40809 compact_area_constraint.push_back(area_constraint[0]);
40813 for(
unsigned i = 1;
i < n_vertex;
i+=2)
40817 if (vector_bnd_vertices[
i].size()!=0)
40819 compact_area_constraint.push_back(area_constraint[
i-1]);
40821 if (
i < n_area_constraint)
40823 compact_area_constraint.push_back(area_constraint[
i]);
40830 const double new_area_constraint =
40831 (area_constraint[
i-1] + area_constraint[
i]) / 2.0;
40832 compact_area_constraint.push_back(new_area_constraint);
40839 if( n_vertex != compact_vector.size() )
40841 unrefinement_applied =
true;
40845 n_vertex = compact_vector.size();
40846 vector_bnd_vertices.resize(n_vertex);
40847 for(
unsigned i = 0;
i < n_vertex;
i++)
40849 vector_bnd_vertices[
i].resize(2);
40850 vector_bnd_vertices[
i][0] = compact_vector[
i][0];
40851 vector_bnd_vertices[
i][1] = compact_vector[
i][1];
40855 unsigned ntarget_areas = compact_area_constraint.size();
40856 area_constraint.resize(ntarget_areas);
40857 for(
unsigned i = 0;
i < ntarget_areas;
i++)
40859 area_constraint[
i] = compact_area_constraint[
i];
40864 return unrefinement_applied;
40875 template <
class ELEMENT>
40883 bool refinement_applied =
false;
40886 if (!Do_shared_boundary_refinement_constrained_by_target_areas)
40888 return refinement_applied;
40892 unsigned nsegments = vector_bnd_vertices.size() - 1;
40899 const double constant_value = 4.0/sqrt(3.0);
40901 for (
unsigned s = 0;
s < nsegments;
s++)
40907 const double x1 = left_vertex[0];
40908 const double y1 = left_vertex[1];
40909 const double x2 = right_vertex[0];
40910 const double y2 = right_vertex[1];
40913 const double segment_length =
40914 sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
40917 const double new_segment_length =
40918 sqrt(constant_value*area_constraint[
s]);
40921 const double n_seg_double = new_segment_length / segment_length;
40926 nseg+=
static_cast<unsigned>(std::floor(1.0/n_seg_double));
40930 tmp_bnd_vertices.push_back(left_vertex);
40937 double incrementx = (right_vertex[0] - left_vertex[0])/(
double)(nseg);
40938 double incrementy = (right_vertex[1] - left_vertex[1])/(
double)(nseg);
40939 for (
unsigned i = 1;
i < nseg;
i++)
40942 tmp_vertex[0] = left_vertex[0] + incrementx*
i;
40943 tmp_vertex[1] = left_vertex[1] + incrementy*
i;
40944 tmp_bnd_vertices.push_back(tmp_vertex);
40952 tmp_bnd_vertices.push_back(vector_bnd_vertices[nsegments]);
40957 nsegments = tmp_bnd_vertices.size() - 1;
40958 if( nsegments != vector_bnd_vertices.size() - 1 )
40960 refinement_applied =
true;
40963 vector_bnd_vertices.resize(nsegments + 1);
40964 for(
unsigned i = 0;
i < nsegments + 1;
i++)
40966 vector_bnd_vertices[
i].resize(2);
40967 vector_bnd_vertices[
i][0] = tmp_bnd_vertices[
i][0];
40968 vector_bnd_vertices[
i][1] = tmp_bnd_vertices[
i][1];
40972 return refinement_applied;
40979 template <
class ELEMENT>
40991 get_face_mesh_representation(polygon_pt,face_mesh_pt);
40999 const unsigned n_polyline = polygon_pt->
npolyline();
41002 for(
unsigned p=0;p<n_polyline;p++)
41015 std::set<Vector<double> > vertex_nodes;
41026 #ifdef OOMPH_HAS_MPI
41053 const unsigned nface_element = face_mesh_pt[p]->nelement();
41059 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41061 for(
unsigned ef=0;ef<nface_element;++ef)
41063 FiniteElement* ele_face_pt = face_mesh_pt[p]->finite_element_pt(ef);
41065 #ifdef OOMPH_HAS_MPI
41066 if (this->is_mesh_distributed())
41069 if (ele_face_pt->
is_halo()) {
continue;}
41073 non_halo_face_element_pt.push_back(ele_face_pt);
41074 face_element_index_on_boundary[ele_face_pt] = ef;
41078 const unsigned nnon_halo_face_element = non_halo_face_element_pt.size();
41081 std::map<FiniteElement*,bool> face_element_done;
41084 unsigned nsorted_face_elements = 0;
41086 #ifdef OOMPH_HAS_MPI
41088 unsigned nsub_boundaries = 0;
41089 #endif // #ifdef OOMPH_HAS_MPI
41093 while(nsorted_face_elements < nnon_halo_face_element)
41098 bool found_initial_face_element =
false;
41101 unsigned iface = 0;
41102 for (iface = 0; iface < nnon_halo_face_element; iface++)
41104 ele_face_pt = non_halo_face_element_pt[iface];
41106 if (!face_element_done[ele_face_pt])
41109 found_initial_face_element =
true;
41111 nsorted_face_elements++;
41118 if (!found_initial_face_element)
41120 std::ostringstream error_message;
41122 <<
"Could not find an initial face element for the current segment\n";
41125 "RefineableTriangleMesh::update_polygon_after_restart()",
41126 OOMPH_EXCEPTION_LOCATION);
41133 std::set<Vector<double> > local_vertex_nodes;
41145 unsigned nnode = ele_face_pt->
nnode();
41149 vertex_coord[0] = bound_left[0];
41152 for(
unsigned i=0;
i<2;
i++)
41154 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
41156 local_vertex_nodes.insert(vertex_coord);
41160 ele_face_pt->
node_pt(nnode-1)->
41161 get_coordinates_on_boundary(bound,bound_right);
41162 vertex_coord[0] = bound_right[0];
41165 for(
unsigned i=0;
i<2;
i++)
41167 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
41169 local_vertex_nodes.insert(vertex_coord);
41173 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
41176 face_element_done[ele_face_pt] =
true;
41184 bool face_element_added =
false;
41193 for (
unsigned iiface=iface;iiface<nnon_halo_face_element;iiface++)
41195 face_element_added =
false;
41196 ele_face_pt = non_halo_face_element_pt[iiface];
41197 if (!face_element_done[ele_face_pt])
41200 nnode = ele_face_pt->nnode();
41201 Node* left_node_pt = ele_face_pt->node_pt(0);
41202 Node* right_node_pt = ele_face_pt->node_pt(nnode-1);
41204 if (left_node_pt == first_node_pt)
41206 first_node_pt = right_node_pt;
41207 face_element_added =
true;
41209 else if (left_node_pt == last_node_pt)
41211 last_node_pt = right_node_pt;
41212 face_element_added =
true;
41214 else if (right_node_pt == first_node_pt)
41216 first_node_pt = left_node_pt;
41217 face_element_added =
true;
41219 else if (right_node_pt == last_node_pt)
41221 last_node_pt = left_node_pt;
41222 face_element_added =
true;
41225 if (face_element_added)
41230 vertex_coord[0] = bound_left[0];
41233 for(
unsigned i=0;
i<2;
i++)
41235 vertex_coord[
i+1] = left_node_pt->
x(
i);
41237 local_vertex_nodes.insert(vertex_coord);
41242 vertex_coord[0] = bound_right[0];
41245 for(
unsigned i=0;
i<2;
i++)
41247 vertex_coord[
i+1] = right_node_pt->
x(
i);
41249 local_vertex_nodes.insert(vertex_coord);
41253 face_element_done[ele_face_pt] =
true;
41254 nsorted_face_elements++;
41261 }
while(face_element_added &&
41262 (nsorted_face_elements < nnon_halo_face_element));
41270 const unsigned nlocal_nodes = local_vertex_nodes.size();
41272 local_tmp_vector_vertex_node.resize(nlocal_nodes);
41275 unsigned counter = 0;
41276 std::set<Vector<double> >::iterator it_vertex;
41277 for (it_vertex = local_vertex_nodes.begin();
41278 it_vertex != local_vertex_nodes.end();
41281 local_tmp_vector_vertex_node[counter].resize(3);
41282 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
41283 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
41284 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
41295 local_vertex_nodes.clear();
41300 unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
41301 for (
unsigned i = 0;
i < nnew_nodes;
i++)
41303 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
41304 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
41305 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
41306 vertex_nodes.insert(vertex_coord);
41307 local_vertex_nodes.insert(vertex_coord);
41310 #ifdef OOMPH_HAS_MPI
41311 if (this->is_mesh_distributed())
41315 sub_vertex_nodes.push_back(local_vertex_nodes);
41324 unsigned npoly_vertex = vertex_nodes.size();
41325 tmp_vector_vertex_node.resize(npoly_vertex);
41326 unsigned count = 0;
41327 std::set<Vector<double> >::iterator it;
41328 for(it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
41330 tmp_vector_vertex_node[count].resize(3);
41331 tmp_vector_vertex_node[count][0] = (*it)[0];
41332 tmp_vector_vertex_node[count][1] = (*it)[1];
41333 tmp_vector_vertex_node[count][2] = (*it)[2];
41337 #ifdef OOMPH_HAS_MPI
41340 unsigned nsub_boundaries_set = sub_vertex_nodes.size();
41341 if (nsub_boundaries_set != nsub_boundaries)
41343 std::ostringstream error_message;
41345 <<
"The number of found sub-boundaries and the number of counted\n"
41346 <<
"sub-boundaries are different:\n"
41347 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
41348 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n";
41350 "RefineableTriangleMesh::update_polygon_after_restart()",
41351 OOMPH_EXCEPTION_LOCATION);
41356 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41359 this->Boundary_was_splitted[bound] =
true;
41361 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
41362 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41365 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
41366 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
41367 unsigned subcount = 0;
41368 std::set<Vector<double> >::iterator subit;
41369 for(subit = sub_vertex_nodes[isub].begin();
41370 subit != sub_vertex_nodes[isub].end(); ++subit)
41372 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
41373 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
41374 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
41375 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
41381 #endif // OOMPH_HAS_MPI
41386 unsigned n_vertex=tmp_vector_vertex_node.size();
41389 vector_vertex_node.resize(n_vertex);
41390 for(
unsigned i=0;
i<n_vertex;
i++)
41392 vector_vertex_node[
i].resize(2);
41393 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
41394 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
41397 #ifdef OOMPH_HAS_MPI
41400 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41405 sub_vector_vertex_node.resize(nsub_boundaries);
41406 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41408 const unsigned subn_vertex =
41409 sub_tmp_vector_vertex_node[isub].size();
41411 sub_vector_vertex_node[isub].resize(subn_vertex);
41412 for(
unsigned i=0;
i<subn_vertex;
i++)
41414 sub_vector_vertex_node[isub][
i].resize(2);
41415 sub_vector_vertex_node[isub][
i][0]=
41416 sub_tmp_vector_vertex_node[isub][
i][1];
41417 sub_vector_vertex_node[isub][
i][1]=
41418 sub_tmp_vector_vertex_node[isub][
i][2];
41428 #endif // OOMPH_HAS_MPI
41433 #ifdef OOMPH_HAS_MPI
41437 if (!this->is_mesh_distributed())
41444 unsigned n_prev_vertex =
41446 final_vertex_of_previous_segment =
41448 vertex_coordinate(n_prev_vertex-1);
41450 unsigned prev_seg_boundary_id =
41455 double error = 0.0;
41456 for(
unsigned i=0;
i<2;
i++)
41458 const double dist =
41459 final_vertex_of_previous_segment[
i] -
41460 (*vector_vertex_node.begin())[
i];
41461 error += dist*dist;
41463 error = sqrt(error);
41471 double rev_error = 0.0;
41472 for(
unsigned i=0;
i<2;
i++)
41474 const double dist =
41475 final_vertex_of_previous_segment[
i] -
41476 (*--vector_vertex_node.end())[
i];
41477 rev_error += dist*dist;
41479 rev_error = sqrt(rev_error);
41493 initial_vertex_of_previous_segment =
41495 vertex_coordinate(0);
41497 unsigned prev_seg_boundary_id =
41502 double error = 0.0;
41503 for(
unsigned i=0;
i<2;
i++)
41505 const double dist =
41506 initial_vertex_of_previous_segment[
i] -
41507 (*vector_vertex_node.begin())[
i];
41508 error += dist*dist;
41510 error = sqrt(error);
41518 double rev_error = 0.0;
41519 for(
unsigned i=0;
i<2;
i++)
41521 const double dist =
41522 initial_vertex_of_previous_segment[
i] -
41523 (*--vector_vertex_node.end())[
i];
41524 rev_error += dist*dist;
41526 rev_error = sqrt(rev_error);
41532 std::ostringstream error_stream;
41534 <<
"The distance between the first node of the current\n"
41535 <<
"line segment (boundary " << bound <<
") and either end of "
41536 <<
"the previous line segment\n"
41537 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than "
41538 <<
"the desired tolerance " <<
41540 <<
"This suggests that the polylines defining the polygonal\n"
41541 <<
"representation are not properly ordered.\n"
41542 <<
"Fail on last vertex of polyline: ("
41543 << prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
41544 << bound <<
").\nThis should have failed when first trying to"
41545 <<
" construct the\npolygon.\n";
41547 "RefineableTriangleMesh::update_polygon_after_restart()",
41548 OOMPH_EXCEPTION_LOCATION);
41554 std::reverse(vector_vertex_node.begin(),
41555 vector_vertex_node.end());
41568 std::ostringstream error_stream;
41570 <<
"The distance between the first node of the current\n"
41571 <<
"line segment (boundary " << bound <<
") and either end of "
41572 <<
"the previous line segment\n"
41573 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
41574 <<
"desired tolerance " <<
41576 <<
"This suggests that the polylines defining the polygonal\n"
41577 <<
"representation are not properly ordered.\n"
41578 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
41579 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
41580 <<
"This should have failed when first trying to construct the\n"
41583 error_stream.str(),
41584 "RefineableTriangleMesh::update_polygon_after_restart()",
41585 OOMPH_EXCEPTION_LOCATION);
41591 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
41606 n_vertex = vector_vertex_node.size();
41626 double unrefinement_tolerance=
41630 double refinement_tolerance=
41635 unrefinement_tolerance);
41637 refinement_tolerance);
41647 this->copy_connection_information(polygon_pt->
polyline_pt(p),
41648 tmp_curve_section_pt);
41654 bool delete_it_on_destructor =
false;
41656 std::set<TriangleMeshCurveSection*>::iterator it =
41659 if (it!=this->Free_curve_section_pt.end())
41661 this->Free_curve_section_pt.erase(it);
41663 delete_it_on_destructor =
true;
41673 if (delete_it_on_destructor)
41678 #ifdef OOMPH_HAS_MPI
41681 if (this->is_mesh_distributed() && nsub_boundaries > 1)
41686 this->Boundary_subpolylines[bound].clear();
41688 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
41689 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
41698 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
41710 #endif // OOMPH_HAS_MPI
41716 delete mesh_geom_obj_pt;
41721 for(
unsigned p=0;p<n_polyline;p++)
41723 face_mesh_pt[p]->flush_node_storage();
41724 delete face_mesh_pt[p];
41733 template <
class ELEMENT>
41744 get_face_mesh_representation(open_curve_pt,face_mesh_pt);
41752 const unsigned ncurve_section = open_curve_pt->
ncurve_section();
41754 for(
unsigned cs = 0; cs < ncurve_section; cs++)
41774 const unsigned nface_element = face_mesh_pt[cs]->nelement();
41781 std::map<FiniteElement*,unsigned> face_element_index_on_boundary;
41784 std::map<FiniteElement*,bool> face_element_done;
41786 for(
unsigned ef = 0; ef < nface_element; ++ef)
41788 FiniteElement* ele_face_pt = face_mesh_pt[cs]->finite_element_pt(ef);
41793 #ifdef OOMPH_HAS_MPI
41794 if (this->is_mesh_distributed())
41797 if (ele_face_pt->
is_halo()) {
continue;}
41802 if (!face_element_done[ele_face_pt])
41807 non_halo_doubled_face_element_pt.push_back(ele_face_pt);
41809 face_element_index_on_boundary[ele_face_pt] = ef;
41811 face_element_done[ele_face_pt] =
true;
41813 const unsigned nnodes = ele_face_pt->nnode();
41816 Node* left_node_pt = ele_face_pt->node_pt(0);
41817 Node* right_node_pt = ele_face_pt->node_pt(nnodes-1);
41822 bool found_other_side_face_ele =
false;
41824 for (
unsigned iface = 0; iface < nface_element; iface++)
41828 face_mesh_pt[cs]->finite_element_pt(iface);
41830 if (!face_element_done[cele_face_pt])
41832 Node* cleft_node_pt = cele_face_pt->node_pt(0);
41833 Node* cright_node_pt = cele_face_pt->node_pt(nnodes-1);
41836 if ((left_node_pt == cleft_node_pt &&
41837 right_node_pt == cright_node_pt) ||
41838 (left_node_pt == cright_node_pt &&
41839 right_node_pt == cleft_node_pt))
41842 non_halo_doubled_face_element_pt.push_back(cele_face_pt);
41844 face_element_done[cele_face_pt] =
true;
41846 face_element_index_on_boundary[cele_face_pt] = iface;
41849 found_other_side_face_ele =
true;
41857 if (!found_other_side_face_ele)
41859 std::ostringstream error_message;
41861 <<
"The face element at the other side of the boundary ("
41862 << bound <<
") was not found!!\n"
41863 <<
"These are the nodes of the face element:\n"
41864 <<
"("<<left_node_pt->
x(0)<<
", "<<left_node_pt->
x(1)<<
") "
41865 <<
"and ("<<right_node_pt->
x(0)<<
","<<right_node_pt->
x(1)<<
")\n\n";
41867 "RefineableTriangleMesh::update_open_curve_after_restart()",
41868 OOMPH_EXCEPTION_LOCATION);
41877 face_element_done.clear();
41882 std::set<Vector<double> > vertex_nodes;
41893 #ifdef OOMPH_HAS_MPI
41898 std::vector<bool> internal_to_shared_boundary;
41923 unsigned nsorted_face_elements = 0;
41925 #ifdef OOMPH_HAS_MPI
41927 unsigned nsub_boundaries = 0;
41928 #endif // #ifdef OOMPH_HAS_MPI
41931 const unsigned nnon_halo_doubled_face_ele =
41932 non_halo_doubled_face_element_pt.size();
41936 while(nsorted_face_elements < nnon_halo_doubled_face_ele)
41942 bool found_initial_face_element =
false;
41948 bool both_root_face_elements_are_nonhalo =
false;
41950 unsigned iface = 0;
41951 for (iface = 0; iface < nnon_halo_doubled_face_ele; iface+=2)
41953 ele_face_pt = non_halo_doubled_face_element_pt[iface];
41955 if (!face_element_done[ele_face_pt])
41958 face_element_done[ele_face_pt] =
true;
41960 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iface+1];
41962 face_element_done[repeated_ele_face_pt] =
true;
41964 #ifdef OOMPH_HAS_MPI
41965 if (!repeated_ele_face_pt->
is_halo())
41966 {both_root_face_elements_are_nonhalo =
true;}
41967 #endif // #ifdef OOMPH_HAS_MPI
41971 nsorted_face_elements+=2;
41975 found_initial_face_element =
true;
41982 if (!found_initial_face_element)
41984 std::ostringstream error_message;
41986 <<
"Could not find an initial face element for the current segment\n";
41989 OOMPH_CURRENT_FUNCTION,
41990 OOMPH_EXCEPTION_LOCATION);
41997 std::set<Vector<double> > local_vertex_nodes;
42009 const unsigned nnode = ele_face_pt->
nnode();
42013 vertex_coord[0] = bound_left[0];
42016 for(
unsigned i=0;
i<2;
i++)
42018 vertex_coord[
i+1] = ele_face_pt->
node_pt(0)->
x(
i);
42020 local_vertex_nodes.insert(vertex_coord);
42026 vertex_coord[0] = bound_right[0];
42029 for(
unsigned i=0;
i<2;
i++)
42031 vertex_coord[
i+1] = ele_face_pt->
node_pt(nnode-1)->
x(
i);
42033 local_vertex_nodes.insert(vertex_coord);
42037 Node *last_node_pt = ele_face_pt->
node_pt(nnode-1);
42041 bool face_element_added =
false;
42051 for (
unsigned iiface=iface;
42052 iiface<nnon_halo_doubled_face_ele;iiface+=2)
42054 face_element_added =
false;
42055 ele_face_pt = non_halo_doubled_face_element_pt[iiface];
42062 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42063 bool both_face_elements_are_nonhalo =
false;
42065 #ifdef OOMPH_HAS_MPI
42066 if (!repeated_ele_face_pt->
is_halo())
42067 {both_face_elements_are_nonhalo =
true;}
42068 #endif // #ifdef OOMPH_HAS_MPI
42070 if (!face_element_done[ele_face_pt] &&
42071 (both_face_elements_are_nonhalo ==
42072 both_root_face_elements_are_nonhalo))
42075 const unsigned nlnode = ele_face_pt->
nnode();
42077 Node* right_node_pt = ele_face_pt->
node_pt(nlnode-1);
42079 if (left_node_pt == first_node_pt)
42081 first_node_pt = right_node_pt;
42082 face_element_added =
true;
42084 else if (left_node_pt == last_node_pt)
42086 last_node_pt = right_node_pt;
42087 face_element_added =
true;
42089 else if (right_node_pt == first_node_pt)
42091 first_node_pt = left_node_pt;
42092 face_element_added =
true;
42094 else if (right_node_pt == last_node_pt)
42096 last_node_pt = left_node_pt;
42097 face_element_added =
true;
42100 if (face_element_added)
42105 vertex_coord[0] = bound_left[0];
42108 for(
unsigned i=0;
i<2;
i++)
42110 vertex_coord[
i+1] = left_node_pt->
x(
i);
42112 local_vertex_nodes.insert(vertex_coord);
42117 vertex_coord[0] = bound_right[0];
42120 for(
unsigned i=0;
i<2;
i++)
42122 vertex_coord[
i+1] = right_node_pt->
x(
i);
42124 local_vertex_nodes.insert(vertex_coord);
42128 face_element_done[ele_face_pt] =
true;
42131 repeated_ele_face_pt = non_halo_doubled_face_element_pt[iiface+1];
42132 face_element_done[repeated_ele_face_pt] =
true;
42134 nsorted_face_elements+=2;
42141 }
while(face_element_added &&
42142 (nsorted_face_elements < nnon_halo_doubled_face_ele));
42150 const unsigned nlocal_nodes = local_vertex_nodes.size();
42152 local_tmp_vector_vertex_node.resize(nlocal_nodes);
42155 unsigned counter = 0;
42156 std::set<Vector<double> >::iterator it_vertex;
42157 for (it_vertex = local_vertex_nodes.begin();
42158 it_vertex != local_vertex_nodes.end();
42161 local_tmp_vector_vertex_node[counter].resize(3);
42162 local_tmp_vector_vertex_node[counter][0] = (*it_vertex)[0];
42163 local_tmp_vector_vertex_node[counter][1] = (*it_vertex)[1];
42164 local_tmp_vector_vertex_node[counter][2] = (*it_vertex)[2];
42171 if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] <
42172 local_tmp_vector_vertex_node[0][2])
42174 std::reverse(local_tmp_vector_vertex_node.begin(),
42175 local_tmp_vector_vertex_node.end());
42177 else if (local_tmp_vector_vertex_node[nlocal_nodes-1][2] ==
42178 local_tmp_vector_vertex_node[0][2])
42180 if (local_tmp_vector_vertex_node[nlocal_nodes-1][1] <
42181 local_tmp_vector_vertex_node[0][1])
42183 std::reverse(local_tmp_vector_vertex_node.begin(),
42184 local_tmp_vector_vertex_node.end());
42195 local_vertex_nodes.clear();
42200 const unsigned nnew_nodes = local_tmp_vector_vertex_node.size();
42201 for (
unsigned i = 0;
i < nnew_nodes;
i++)
42203 vertex_coord[0] = local_tmp_vector_vertex_node[
i][0];
42204 vertex_coord[1] = local_tmp_vector_vertex_node[
i][1];
42205 vertex_coord[2] = local_tmp_vector_vertex_node[
i][2];
42206 vertex_nodes.insert(vertex_coord);
42207 local_vertex_nodes.insert(vertex_coord);
42210 #ifdef OOMPH_HAS_MPI
42211 if (this->is_mesh_distributed())
42216 sub_vertex_nodes.push_back(local_vertex_nodes);
42222 if (both_root_face_elements_are_nonhalo)
42223 {internal_to_shared_boundary.push_back(
false);}
42225 {internal_to_shared_boundary.push_back(
true);}
42235 const unsigned npoly_vertex = vertex_nodes.size();
42236 tmp_vector_vertex_node.resize(npoly_vertex);
42237 unsigned count = 0;
42238 std::set<Vector<double> >::iterator it;
42239 for (it = vertex_nodes.begin(); it!=vertex_nodes.end(); ++it)
42241 tmp_vector_vertex_node[count].resize(3);
42242 tmp_vector_vertex_node[count][0] = (*it)[0];
42243 tmp_vector_vertex_node[count][1] = (*it)[1];
42244 tmp_vector_vertex_node[count][2] = (*it)[2];
42248 #ifdef OOMPH_HAS_MPI
42253 const unsigned nsub_boundaries_set = sub_vertex_nodes.size();
42254 const unsigned ninternal_to_shared_boundaries =
42255 internal_to_shared_boundary.size();
42256 if (nsub_boundaries_set != ninternal_to_shared_boundaries)
42258 std::ostringstream error_message;
42260 <<
"The number of found sub-boundaries and the number of marked "
42261 <<
"internal\nboundaries are different\n"
42262 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
42263 <<
"Number of marked internal boundaries: ("
42264 << ninternal_to_shared_boundaries <<
")\n\n";
42266 "RefineableTriangleMesh::update_open_curve_after_restart()",
42267 OOMPH_EXCEPTION_LOCATION);
42273 if (nsub_boundaries_set != nsub_boundaries)
42275 std::ostringstream error_message;
42277 <<
"The number of found sub-boundaries and the number of counted\n"
42278 <<
"sub-boundaries are different:\n"
42279 <<
"Number of found sub-boundaries: ("<<nsub_boundaries_set<<
")\n"
42280 <<
"Number of counted sub-boundaries: ("<<nsub_boundaries<<
")\n\n";
42282 "RefineableTriangleMesh::update_open_curve_after_restart()",
42283 OOMPH_EXCEPTION_LOCATION);
42288 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42291 this->Boundary_was_splitted[bound] =
true;
42293 sub_tmp_vector_vertex_node.resize(nsub_boundaries);
42294 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42297 const unsigned nsubpoly_vertex = sub_vertex_nodes[isub].size();
42298 sub_tmp_vector_vertex_node[isub].resize(nsubpoly_vertex);
42299 unsigned subcount = 0;
42300 std::set<Vector<double> >::iterator subit;
42301 for(subit = sub_vertex_nodes[isub].begin();
42302 subit != sub_vertex_nodes[isub].end(); ++subit)
42304 sub_tmp_vector_vertex_node[isub][subcount].resize(3);
42305 sub_tmp_vector_vertex_node[isub][subcount][0] = (*subit)[0];
42306 sub_tmp_vector_vertex_node[isub][subcount][1] = (*subit)[1];
42307 sub_tmp_vector_vertex_node[isub][subcount][2] = (*subit)[2];
42313 #endif // OOMPH_HAS_MPI
42317 unsigned n_vertex=tmp_vector_vertex_node.size();
42320 vector_vertex_node.resize(n_vertex);
42321 for(
unsigned i=0;
i<n_vertex;
i++)
42323 vector_vertex_node[
i].resize(2);
42324 vector_vertex_node[
i][0]=tmp_vector_vertex_node[
i][1];
42325 vector_vertex_node[
i][1]=tmp_vector_vertex_node[
i][2];
42328 #ifdef OOMPH_HAS_MPI
42331 if (this->is_mesh_distributed() && nsub_boundaries > 1)
42336 sub_vector_vertex_node.resize(nsub_boundaries);
42337 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42339 const unsigned subn_vertex =
42340 sub_tmp_vector_vertex_node[isub].size();
42342 sub_vector_vertex_node[isub].resize(subn_vertex);
42343 for(
unsigned i=0;
i<subn_vertex;
i++)
42345 sub_vector_vertex_node[isub][
i].resize(2);
42346 sub_vector_vertex_node[isub][
i][0]=
42347 sub_tmp_vector_vertex_node[isub][
i][1];
42348 sub_vector_vertex_node[isub][
i][1]=
42349 sub_tmp_vector_vertex_node[isub][
i][2];
42359 #endif // OOMPH_HAS_MPI
42364 #ifdef OOMPH_HAS_MPI
42368 if (!this->is_mesh_distributed())
42375 unsigned n_prev_vertex =
42377 final_vertex_of_previous_segment =
42379 vertex_coordinate(n_prev_vertex-1);
42381 unsigned prev_seg_boundary_id =
42386 double error = 0.0;
42387 for(
unsigned i=0;
i<2;
i++)
42389 const double dist =
42390 final_vertex_of_previous_segment[
i] -
42391 (*vector_vertex_node.begin())[
i];
42392 error += dist*dist;
42394 error = sqrt(error);
42402 double rev_error = 0.0;
42403 for(
unsigned i=0;
i<2;
i++)
42405 const double dist =
42406 final_vertex_of_previous_segment[
i] -
42407 (*--vector_vertex_node.end())[
i];
42408 rev_error += dist*dist;
42410 rev_error = sqrt(rev_error);
42424 initial_vertex_of_previous_segment =
42427 unsigned prev_seg_boundary_id =
42432 double error = 0.0;
42433 for(
unsigned i=0;
i<2;
i++)
42435 const double dist =
42436 initial_vertex_of_previous_segment[
i] -
42437 (*vector_vertex_node.begin())[
i];
42438 error += dist*dist;
42440 error = sqrt(error);
42448 double rev_error = 0.0;
42449 for(
unsigned i=0;
i<2;
i++)
42451 const double dist =
42452 initial_vertex_of_previous_segment[
i] -
42453 (*--vector_vertex_node.end())[
i];
42454 rev_error += dist*dist;
42456 rev_error = sqrt(rev_error);
42462 std::ostringstream error_stream;
42464 <<
"The distance between the first node of the current\n"
42465 <<
"line segment (boundary "<<bound<<
") and either end of "
42466 <<
"the previous line segment\n"
42467 <<
"(boundary "<<prev_seg_boundary_id<<
") is bigger than"
42468 <<
" the desired tolerance " <<
42470 <<
"This suggests that the polylines defining the polygonal\n"
42471 <<
"representation are not properly ordered.\n"
42472 <<
"Fail on last vertex of polyline: ("
42473 <<prev_seg_boundary_id<<
") and\nfirst vertex of polyline ("
42474 <<bound<<
").\nThis should have failed when first trying to "
42475 <<
"construct the\npolygon.\n";
42477 "RefineableTriangleMesh::update_open_curve_after_restart()",
42478 OOMPH_EXCEPTION_LOCATION);
42484 std::reverse(vector_vertex_node.begin(),
42485 vector_vertex_node.end());
42498 std::ostringstream error_stream;
42500 <<
"The distance between the first node of the current\n"
42501 <<
"line segment (boundary " << bound <<
") and either end of "
42502 <<
"the previous line segment\n"
42503 <<
"(boundary " << prev_seg_boundary_id <<
") is bigger than the "
42504 <<
"desired tolerance " <<
42506 <<
"This suggests that the polylines defining the polygonal\n"
42507 <<
"representation are not properly ordered.\n"
42508 <<
"Fail on last vertex of polyline: (" << prev_seg_boundary_id
42509 <<
") and\nfirst vertex of polyline (" << bound <<
").\n"
42510 <<
"This should have failed when first trying to construct the\n"
42513 error_stream.str(),
42514 "RefineableTriangleMesh::update_open_curve_after_restart()",
42515 OOMPH_EXCEPTION_LOCATION);
42521 std::reverse(vector_vertex_node.begin(),vector_vertex_node.end());
42539 n_vertex = vector_vertex_node.size();
42552 double unrefinement_tolerance=
42556 double refinement_tolerance=
42571 this->copy_connection_information(open_curve_pt->
polyline_pt(cs),
42572 tmp_curve_section_pt);
42578 bool delete_it_on_destructor =
false;
42580 std::set<TriangleMeshCurveSection*>::iterator it =
42583 if (it!=this->Free_curve_section_pt.end())
42585 this->Free_curve_section_pt.erase(it);
42587 delete_it_on_destructor =
true;
42595 this->Boundary_curve_section_pt[bound]=open_curve_pt->
curve_section_pt(cs);
42597 if (delete_it_on_destructor)
42602 #ifdef OOMPH_HAS_MPI
42606 if (this->is_mesh_distributed() && nsub_boundaries == 1)
42609 this->Boundary_marked_as_shared_boundary[bound].clear();
42612 this->Boundary_marked_as_shared_boundary[bound].push_back(
42613 internal_to_shared_boundary[0]);
42617 else if (this->is_mesh_distributed() && nsub_boundaries > 1)
42622 this->Boundary_subpolylines[bound].clear();
42624 this->Boundary_subpolylines[bound].resize(nsub_boundaries);
42627 this->Boundary_marked_as_shared_boundary[bound].clear();
42630 this->Boundary_marked_as_shared_boundary[bound].resize(nsub_boundaries);
42631 for (
unsigned isub = 0; isub < nsub_boundaries; isub++)
42640 this->Boundary_subpolylines[bound][isub] = sub_tmp_polyline_pt;
42644 this->Boundary_marked_as_shared_boundary[bound][isub] =
42645 internal_to_shared_boundary[isub];
42655 #endif // OOMPH_HAS_MPI
42661 delete mesh_geom_obj_pt;
42666 for(
unsigned p = 0; p < ncurve_section; p++)
42668 face_mesh_pt[p]->flush_node_storage();
42669 delete face_mesh_pt[p];
42674 #ifdef OOMPH_HAS_MPI
42678 template <
class ELEMENT>
42681 &vector_polyline_pt)
42684 const unsigned npolylines = vector_polyline_pt.size();
42685 for (
unsigned pp = 0; pp < npolylines; pp++)
42688 const unsigned b = vector_polyline_pt[pp]->boundary_id();
42693 std::map<std::pair<Node*, Node*>,
FiniteElement*> halo_edge_element_pt;
42694 std::map<std::pair<Node*, Node*>,
FiniteElement*> nonhalo_edge_element_pt;
42701 const unsigned nshared_bound_ele = this->nshared_boundary_element(b);
42702 for (
unsigned e = 0;
e < nshared_bound_ele;
e++)
42705 FiniteElement* current_ele_pt = this->shared_boundary_element_pt(b,
e);
42708 Node *first_node_pt = current_ele_pt->
node_pt(0);
42709 Node *second_node_pt = current_ele_pt->
node_pt(1);
42710 Node *third_node_pt = current_ele_pt->
node_pt(2);
42713 if (!current_ele_pt->
is_halo())
42716 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42717 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42719 nonhalo_edge_nodes_pt.push_back(second_node_pt);
42720 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42722 nonhalo_edge_nodes_pt.push_back(third_node_pt);
42723 nonhalo_edge_nodes_pt.push_back(first_node_pt);
42726 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42728 nonhalo_edge_element_pt[edge1] = current_ele_pt;
42730 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42732 nonhalo_edge_element_pt[edge2] = current_ele_pt;
42734 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42736 nonhalo_edge_element_pt[edge3] = current_ele_pt;
42741 halo_edge_nodes_pt.push_back(first_node_pt);
42742 halo_edge_nodes_pt.push_back(second_node_pt);
42744 halo_edge_nodes_pt.push_back(second_node_pt);
42745 halo_edge_nodes_pt.push_back(third_node_pt);
42747 halo_edge_nodes_pt.push_back(third_node_pt);
42748 halo_edge_nodes_pt.push_back(first_node_pt);
42751 std::pair<Node*, Node*> edge1 = std::make_pair(first_node_pt,
42753 halo_edge_element_pt[edge1] = current_ele_pt;
42755 std::pair<Node*, Node*> edge2 = std::make_pair(second_node_pt,
42757 halo_edge_element_pt[edge2] = current_ele_pt;
42759 std::pair<Node*, Node*> edge3 = std::make_pair(third_node_pt,
42761 halo_edge_element_pt[edge3] = current_ele_pt;
42769 std::map<std::pair<Node*,Node*>,
bool> edge_done;
42778 const unsigned nnonhalo_edge_nodes = nonhalo_edge_nodes_pt.size();
42779 for (
unsigned i = 0;
i < nnonhalo_edge_nodes;
i+=2)
42782 currenti_edge[0] = nonhalo_edge_nodes_pt[
i];
42783 currenti_edge[1] = nonhalo_edge_nodes_pt[
i+1];
42786 std::pair<Node*, Node*> new_edge =
42787 std::make_pair(currenti_edge[0], currenti_edge[1]);
42789 if (!edge_done[new_edge])
42791 const unsigned nhalo_edge_nodes = halo_edge_nodes_pt.size();
42792 for (
unsigned j = 0; j < nhalo_edge_nodes; j+=2)
42795 currentj_edge[0] = halo_edge_nodes_pt[j];
42796 currentj_edge[1] = halo_edge_nodes_pt[j+1];
42799 if (currenti_edge[0] == currentj_edge[0] &&
42800 currenti_edge[1] == currentj_edge[1])
42803 unsorted_edges.push_back(new_edge);
42808 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42809 FiniteElement* halo_ele_pt = halo_edge_element_pt[new_edge];
42811 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42812 tmp_edge_element_pt.push_back(halo_ele_pt);
42815 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42818 edge_done[new_edge] =
true;
42826 else if (currenti_edge[0] == currentj_edge[1] &&
42827 currenti_edge[1] == currentj_edge[0])
42830 std::pair<Node*, Node*> new_edge =
42831 std::make_pair(currenti_edge[0], currenti_edge[1]);
42834 unsorted_edges.push_back(new_edge);
42837 std::pair<Node*, Node*> rev_new_edge =
42838 std::make_pair(currentj_edge[0], currentj_edge[1]);
42843 FiniteElement* nonhalo_ele_pt = nonhalo_edge_element_pt[new_edge];
42844 FiniteElement* halo_ele_pt = halo_edge_element_pt[rev_new_edge];
42846 tmp_edge_element_pt.push_back(nonhalo_ele_pt);
42847 tmp_edge_element_pt.push_back(halo_ele_pt);
42850 unsorted_edges_elements_pt.push_back(tmp_edge_element_pt);
42853 edge_done[new_edge] =
true;
42871 std::map<std::pair<Node*,Node*>,
bool> edge_sorted;
42873 const unsigned nunsorted_edges = unsorted_edges.size();
42878 if (nshared_bound_ele / 2 != nunsorted_edges)
42880 std::ostringstream error_message;
42882 <<
"The number of shared boundary elements (" << nshared_bound_ele
42883 <<
") is not the double\nof the number of unsorted edges ("
42884 << nunsorted_edges <<
") for the current boundary ("<< b <<
")\n\n";
42886 "RefineableTriangleMesh::update_shared_curve_after_restart()",
42887 OOMPH_EXCEPTION_LOCATION);
42891 unsigned nsorted_edges = 0;
42895 std::list<Node*> sorted_nodes;
42898 std::list<FiniteElement*> sorted_edges_elements_pt;
42901 std::pair<Node*,Node*> edge = unsorted_edges[0];
42905 edge_sorted[edge] =
true;
42908 Node *first_node_pt = edge.first;
42909 Node *last_node_pt = edge.second;
42912 sorted_nodes.push_back(first_node_pt);
42913 sorted_nodes.push_back(last_node_pt);
42916 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][0]);
42917 sorted_edges_elements_pt.push_back(unsorted_edges_elements_pt[0][1]);
42921 while (nsorted_edges < nunsorted_edges)
42924 bool node_added =
false;
42928 for (
unsigned iedge = 1; iedge < nunsorted_edges; iedge++)
42930 edge = unsorted_edges[iedge];
42933 if (!edge_sorted[edge])
42936 Node* left_node_pt = edge.first;
42937 Node* right_node_pt = edge.second;
42939 if (left_node_pt == first_node_pt)
42942 sorted_nodes.push_front(right_node_pt);
42943 first_node_pt = right_node_pt;
42947 sorted_edges_elements_pt.push_front(
42948 unsorted_edges_elements_pt[iedge][1]);
42949 sorted_edges_elements_pt.push_front(
42950 unsorted_edges_elements_pt[iedge][0]);
42952 else if (left_node_pt == last_node_pt)
42955 sorted_nodes.push_back(right_node_pt);
42956 last_node_pt = right_node_pt;
42960 sorted_edges_elements_pt.push_back(
42961 unsorted_edges_elements_pt[iedge][0]);
42962 sorted_edges_elements_pt.push_back(
42963 unsorted_edges_elements_pt[iedge][1]);
42965 else if (right_node_pt == first_node_pt)
42968 sorted_nodes.push_front(left_node_pt);
42969 first_node_pt = left_node_pt;
42973 sorted_edges_elements_pt.push_front(
42974 unsorted_edges_elements_pt[iedge][1]);
42975 sorted_edges_elements_pt.push_front(
42976 unsorted_edges_elements_pt[iedge][0]);
42978 else if (right_node_pt == last_node_pt)
42981 sorted_nodes.push_back(left_node_pt);
42982 last_node_pt = left_node_pt;
42986 sorted_edges_elements_pt.push_back(
42987 unsorted_edges_elements_pt[iedge][0]);
42988 sorted_edges_elements_pt.push_back(
42989 unsorted_edges_elements_pt[iedge][1]);
42996 edge_sorted[edge] =
true;
43011 unsigned nvertex = sorted_nodes.size();
43016 unsigned counter = 0;
43017 for (std::list<Node*>::iterator it_nodes = sorted_nodes.begin();
43018 it_nodes != sorted_nodes.end();
43021 polyline_vertices[counter].resize(2);
43022 polyline_vertices[counter][0] = (*it_nodes)->x(0);
43023 polyline_vertices[counter][1] = (*it_nodes)->x(1);
43030 if (polyline_vertices[nvertex-1][1] < polyline_vertices[0][1])
43032 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43034 else if (polyline_vertices[nvertex-1][1] == polyline_vertices[0][1])
43036 if (polyline_vertices[nvertex-1][0] < polyline_vertices[0][0])
43038 std::reverse(polyline_vertices.begin(), polyline_vertices.end());
43051 this->copy_connection_information(curve_section_pt, new_polyline_pt);
43056 bool delete_it_on_destructor =
false;
43060 std::set<TriangleMeshCurveSection*>::iterator it =
43061 this->Free_curve_section_pt.find(curve_section_pt);
43063 if (it!=this->Free_curve_section_pt.end())
43065 this->Free_curve_section_pt.erase(it);
43066 delete curve_section_pt;
43067 delete_it_on_destructor =
true;
43071 vector_polyline_pt[pp] = new_polyline_pt;
43077 this->Boundary_curve_section_pt[b] = new_curve_section_pt;
43079 if (delete_it_on_destructor)
43081 this->Free_curve_section_pt.insert(new_curve_section_pt);
43094 template <
class ELEMENT>
43099 std::ofstream some_file;
43100 fill_boundary_elements_and_nodes_for_internal_boundaries(some_file);
43107 template <
class ELEMENT>
43110 std::ofstream& outfile)
43113 const unsigned nproc = this->communicator_pt()->nproc();
43115 unsigned my_rank = this->communicator_pt()->my_rank();
43118 std::map<unsigned, unsigned> shd_bnd_over_int_bnd =
43119 this->Shared_boundary_overlaps_internal_boundary;
43123 std::set<unsigned> internal_boundary_overlaped;
43127 if (outfile.is_open())
43129 const unsigned nbound = this->nboundary();
43130 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43131 outfile <<
"Number of elements and nodes associated to each "
43132 <<
"boundary before\nfilling elements and nodes\n\n";
43133 for (
unsigned i = 0;
i < nbound;
i++)
43135 outfile <<
"Boundary (" <<
i <<
") Elements ("
43136 << this->nboundary_element(
i) <<
") " <<
"Nodes ("
43137 << this->nboundary_node(
i) <<
")\n";
43142 std::set<unsigned> shared_boundaries_in_this_processor;
43146 for (
unsigned iproc = 0; iproc < nproc; iproc++)
43149 if (iproc != my_rank)
43152 unsigned nshared_boundaries_with_iproc =
43153 this->nshared_boundaries(my_rank, iproc);
43155 if (nshared_boundaries_with_iproc > 0)
43159 bound_shared_with_iproc = this->shared_boundaries_ids(my_rank,
43163 for (
unsigned bs = 0; bs < nshared_boundaries_with_iproc; bs++)
43165 unsigned bnd_id = bound_shared_with_iproc[bs];
43166 shared_boundaries_in_this_processor.insert(bnd_id);
43177 for (std::map<unsigned, unsigned>::iterator it =
43178 shd_bnd_over_int_bnd.begin(); it != shd_bnd_over_int_bnd.end(); it++)
43181 const unsigned shd_bnd_id = (*it).first;
43183 const unsigned int_bnd_id = (*it).second;
43186 std::set<unsigned>::iterator it_set =
43187 shared_boundaries_in_this_processor.find(shd_bnd_id);
43188 if (it_set != shared_boundaries_in_this_processor.end())
43190 internal_boundary_overlaped.insert(int_bnd_id);
43195 const unsigned nbnd_node_shd_bnd = this->nboundary_node(shd_bnd_id);
43199 if (outfile.is_open())
43201 outfile <<
"\nPass info. from shared (" << shd_bnd_id
43202 <<
") to internal (" << int_bnd_id <<
")\n";
43203 outfile <<
"Number of shared boundary nodes: "
43204 << nbnd_node_shd_bnd <<
"\n";
43207 for (
unsigned in = 0; in < nbnd_node_shd_bnd; in++)
43210 Node* bnd_node_pt = this->boundary_node_pt(shd_bnd_id, in);
43212 this->add_boundary_node(int_bnd_id, bnd_node_pt);
43219 const unsigned nbnd_ele_shd_bnd = this->nboundary_element(shd_bnd_id);
43223 if (outfile.is_open())
43225 outfile <<
"Number of shared boundary elements: "
43226 << nbnd_ele_shd_bnd <<
"\n\n";
43231 for (
unsigned ie = 0; ie < nbnd_ele_shd_bnd; ie++)
43234 FiniteElement* bnd_ele_pt = this->boundary_element_pt(shd_bnd_id, ie);
43237 Boundary_element_pt[int_bnd_id].push_back(bnd_ele_pt);
43239 int face_index = this->face_index_at_boundary(shd_bnd_id, ie);
43241 Face_index_at_boundary[int_bnd_id].push_back(face_index);
43246 const unsigned nregions = this->nregion();
43249 for (
unsigned ir = 0 ; ir < nregions; ir++)
43252 const unsigned region_id =
43253 static_cast<unsigned>(this->Region_attribute[ir]);
43256 const unsigned nele_ir = this->nboundary_element_in_region(shd_bnd_id,
43258 for (
unsigned ier = 0; ier < nele_ir; ier++)
43262 this->boundary_element_in_region_pt(shd_bnd_id, region_id, ier);
43265 this->Boundary_region_element_pt[int_bnd_id][region_id].
43266 push_back(bnd_ele_pt);
43270 this->face_index_at_boundary_in_region(shd_bnd_id, region_id, ier);
43272 this->Face_index_region_at_boundary[int_bnd_id][region_id].
43273 push_back(face_index);
43287 if (outfile.is_open())
43289 const unsigned nbound = this->nboundary();
43290 outfile <<
"Number of boundaries: " << nbound <<
"\n\n";
43291 outfile <<
"Number of elements and nodes associated to each "
43292 <<
"boundary after\nfilling elements and nodes\n\n";
43293 for (
unsigned i = 0;
i < nbound;
i++)
43295 outfile <<
"Boundary (" <<
i <<
") Elements ("
43296 << this->nboundary_element(
i) <<
")" <<
" Nodes ("
43297 << this->nboundary_node(
i) <<
")\n";
43305 for (std::set<unsigned>::iterator it = internal_boundary_overlaped.begin();
43306 it != internal_boundary_overlaped.end(); it++)
43308 const unsigned overlaped_internal_bnd_id = (*it);
43311 this->
template setup_boundary_coordinates<ELEMENT>(overlaped_internal_bnd_id);
43316 #endif // #ifdef OOMPH_HAS_MPI
43321 template <
class ELEMENT>
43327 if (!Boundary_coordinate_exists[b])
43343 std::set<Node*> tmp_boundary_node_pt;
43344 const unsigned nboundary_ele = this->nboundary_element(b);
43345 for (
unsigned e = 0;
e < nboundary_ele;
e++)
43349 #ifdef OOMPH_HAS_MPI
43355 int face_index = this->face_index_at_boundary(b,
e);
43358 bulk_ele_pt, face_index);
43361 const unsigned nnodes = face_ele_pt->
nnode();
43362 for (
unsigned i = 0;
i < nnodes;
i++)
43367 tmp_boundary_node_pt.insert(tmp_node_pt);
43371 delete face_ele_pt;
43373 #ifdef OOMPH_HAS_MPI
43380 const unsigned long n_boundary_node = tmp_boundary_node_pt.
size();
43383 if (n_boundary_node==0)
43385 #ifdef OOMPH_HAS_MPI
43387 if (!this->is_mesh_distributed())
43391 #ifdef OOMPH_HAS_MPI
43397 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43401 delete mesh_geom_obj_pt;
43406 delete face_mesh_pt;
43418 unsigned tmp_counter = 0;
43419 for(std::set<Node*>::iterator it_node = tmp_boundary_node_pt.begin();
43420 it_node != tmp_boundary_node_pt.end(); it_node++, tmp_counter++)
43422 Node* nod_pt = (*it_node);
43424 node_coord[0] = b_coord[0];
43425 node_coord[1] = nod_pt->
x(0);
43426 node_coord[2] = nod_pt->
x(1);
43427 old_boundary_node[tmp_counter] = node_coord;
43431 std::sort(old_boundary_node.begin(),old_boundary_node.end());
43442 #ifdef OOMPH_HAS_MPI
43448 const unsigned nsegments = 1;
43449 #endif // #ifdef OOMPH_HAS_MPI
43451 #ifdef OOMPH_HAS_MPI
43456 if (this->is_mesh_distributed())
43461 if (n_new_boundary_node==0)
43465 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43469 delete mesh_geom_obj_pt;
43473 delete face_mesh_pt;
43477 #endif // #ifdef OOMPH_HAS_MPI
43484 for (
unsigned is = 0; is < nsegments; is++)
43486 #ifdef OOMPH_HAS_MPI
43487 const unsigned n_new_boundary_segment_node =
43490 const unsigned n_new_boundary_segment_node = new_mesh_pt->
nboundary_node(b);
43491 #endif // #ifdef OOMPH_HAS_MPI
43495 node_coord.resize(6,0.0);
43496 for(
unsigned n = 0;
n < n_new_boundary_segment_node;
n++)
43498 #ifdef OOMPH_HAS_MPI
43502 #endif // #ifdef OOMPH_HAS_MPI
43504 node_coord[0] = b_coord[0];
43505 node_coord[1] = nod_pt->
x(0);
43506 node_coord[2] = nod_pt->
x(1);
43508 new_boundary_node[
n] = node_coord;
43512 std::sort(new_boundary_node.begin(),new_boundary_node.end());
43519 unsigned old_index = 0;
43520 for(
unsigned n=0;
n<n_new_boundary_segment_node;++
n)
43524 for(
unsigned m=old_index;m<n_boundary_node;++m)
43527 (std::fabs(old_boundary_node[m][1]-new_boundary_node[
n][1])<1.0
e-14)
43529 (std::fabs(old_boundary_node[m][2]-new_boundary_node[
n][2])<1.0
e-14))
43532 new_boundary_node[
n][4] = old_boundary_node[m][0];
43534 new_boundary_node[
n][5] = 1.0;
43545 if((new_boundary_node[0][5]==0.0) ||
43546 (new_boundary_node[n_new_boundary_segment_node-1][5] == 0.0))
43548 std::ostringstream error_stream;
43550 <<
"New boundary coordinates not found for the first and/or last "
43552 <<
"on the boundary " << b <<
". This should not happen because "
43553 <<
"these\nlimits should have been setup in the constructor\n";
43555 <<
"The distance between the new and old nodes is probably outside\n"
43556 <<
"our tolerance.\n";
43557 error_stream.precision(20);
43558 error_stream <<
"Old boundaries: \n";
43560 old_boundary_node[0][1] <<
" " << old_boundary_node[0][2]
43562 old_boundary_node[n_boundary_node-1][1] <<
" " <<
43563 old_boundary_node[n_boundary_node-1][2] <<
"\n";
43564 error_stream <<
"New boundaries: \n" <<
43565 new_boundary_node[0][1] <<
" " << new_boundary_node[0][2] <<
" : " <<
43566 new_boundary_node[n_new_boundary_segment_node-1][1] <<
" " <<
43567 new_boundary_node[n_new_boundary_segment_node-1][2] <<
"\n";
43569 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43570 OOMPH_EXCEPTION_LOCATION);
43576 if (!this->is_mesh_distributed())
43580 new_boundary_node[0][4] = new_boundary_node[0][0];
43583 new_boundary_node[n_new_boundary_segment_node-1][4] =
43584 new_boundary_node[0][5] = 1.0;
43586 new_boundary_node[n_new_boundary_segment_node-1][4] =
43587 new_boundary_node[n_new_boundary_segment_node-1][0];
43588 new_boundary_node[n_new_boundary_segment_node-1][5] = 1.0;
43593 for(
unsigned n=1;
n<n_new_boundary_segment_node-1;++
n)
43596 if(new_boundary_node[
n][5]==0.0)
43599 nodes_to_be_snapped[is].push_back(
43600 static_cast<unsigned>(new_boundary_node[
n][3]));
43604 double zeta_old_low = new_boundary_node[
n-1][0];
43605 double zeta_new_low = new_boundary_node[
n-1][4];
43609 for(
unsigned m=
n+1;m<n_new_boundary_segment_node;++m)
43611 if(new_boundary_node[m][5]==1.0)
43614 double zeta_old_high = new_boundary_node[m][0];
43615 double zeta_new_high = new_boundary_node[m][4];
43617 double frac = (new_boundary_node[
n][0] - zeta_old_low)/
43618 (zeta_old_high - zeta_old_low);
43619 new_boundary_node[
n][4] = zeta_new_low
43620 + frac*(zeta_new_high - zeta_new_low);
43621 new_boundary_node[
n][5] = 1.0;
43629 for(
unsigned n=0;
n<n_new_boundary_segment_node;++
n)
43631 if(new_boundary_node[
n][5]==0)
43634 "New boundary coordinate not assigned\n",
43635 "RefineableTriangleMesh::snap_nodes_onto_boundary()",
43636 OOMPH_EXCEPTION_LOCATION);
43639 #ifdef OOMPH_HAS_MPI
43642 b,is,
static_cast<unsigned>(new_boundary_node[
n][3]))
43643 ->get_coordinates_on_boundary(b,b_coord);
43645 b_coord[0] = new_boundary_node[
n][4];
43647 b,is,
static_cast<unsigned>(new_boundary_node[
n][3]))
43648 ->set_coordinates_on_boundary(b,b_coord);
43652 b,
static_cast<unsigned>(new_boundary_node[
n][3]))
43655 b_coord[0] = new_boundary_node[
n][4];
43657 b,
static_cast<unsigned>(new_boundary_node[
n][3]))
43659 #endif // #ifdef OOMPH_HAS_MPI
43666 create_unsorted_face_mesh_representation(b, face_mesh_pt);
43676 for(
unsigned is = 0; is < nsegments; is++)
43678 const unsigned nnodes_to_snap = nodes_to_be_snapped[is].size();
43680 for (
unsigned in = 0; in < nnodes_to_snap; in++)
43683 unsigned n = nodes_to_be_snapped[is][in];
43684 #ifdef OOMPH_HAS_MPI
43690 #endif // #ifdef OOMPH_HAS_MPI
43694 mesh_geom_obj_pt->
position(b_coord,new_x);
43697 for(
unsigned i=0;
i<2;
i++)
43699 nod_pt->
x(
i) = new_x[
i];
43705 delete mesh_geom_obj_pt;
43709 delete face_mesh_pt;
43716 for (
unsigned j=0;j<6;j++)
43718 dummy_six_node_element.construct_node(j);
43724 for(
unsigned e=0;
e<n_bound_el;
e++)
43729 unsigned nnod=el_pt->
nnode();
43745 "Have a three-noded element that's not a TElement<2,2>",
43746 OOMPH_CURRENT_FUNCTION,
43747 OOMPH_EXCEPTION_LOCATION);
43755 else if ((nnod==6)||(nnod==7))
43766 "Have a six-noded element that's not a TElement<2,3>",
43767 OOMPH_CURRENT_FUNCTION,
43768 OOMPH_EXCEPTION_LOCATION);
43773 "Have a seven-noded element that's not a TElement<2,3>",
43774 OOMPH_CURRENT_FUNCTION,
43775 OOMPH_EXCEPTION_LOCATION);
43795 for(
unsigned i=0;
i<2;
i++)
43806 for(
unsigned i=0;
i<2;
i++)
43822 for(
unsigned i=0;
i<2;
i++)
43833 for(
unsigned i=0;
i<2;
i++)
43849 for(
unsigned i=0;
i<2;
i++)
43860 for(
unsigned i=0;
i<2;
i++)
43878 "Have seven-noded element that's not a TBubbleEnrichedElement<2,3>",
43879 OOMPH_CURRENT_FUNCTION,
43880 OOMPH_EXCEPTION_LOCATION);
43884 for (
unsigned j=0;j<6;j++)
43886 for (
unsigned i=0;
i<2;
i++)
43888 dummy_six_node_element.node_pt(j)->x(
i)=el_pt->
node_pt(j)->
x(
i);
43893 unsigned j_enriched=6;
43899 dummy_six_node_element.interpolated_x(
s,x);
43900 el_pt->
node_pt(j_enriched)->
x(0) = x[0];
43901 el_pt->
node_pt(j_enriched)->
x(1) = x[1];
43908 std::ostringstream error_stream;
43910 <<
"Cannot deal with this particular " << nnod
43911 <<
"-noded element yet.\n"
43912 <<
"Please implement this yourself.\n";
43914 OOMPH_CURRENT_FUNCTION,
43915 OOMPH_EXCEPTION_LOCATION);
43920 for (
unsigned j=0;j<6;j++)
43922 delete dummy_six_node_element.node_pt(j);
43929 #endif // #ifdef OOMPH_HAS_TRIANGLE_LIB